Compare commits

...

244 Commits

Author SHA1 Message Date
Kyle Kienapfel 40af1111c2 CMake: Try add library "LZ4::lz4_shared" if "lz4::lz4" is unavailable
Right now this looks like a distro specific problem, but we'll have to see.

Over on Gentoo: with lz4 1.9.3 there is a lz4::lz4 library target, with 1.9.4 it's no longer
mentioned in the cmake files provided by the  package. (/usr/lib64/cmake/lz4)

arch and openSUSE have lz4 1.9.4 available so I checked there,
they only have .pc files for pkg-config, so asking for "lz4::lz4" works as usual

MSVC does require "lz4::lz4" to be asked for
2022-10-13 17:23:47 -07:00
liamwhite 553be194f6 Merge pull request #9067 from Morph1984/tess-cw
renderer_(opengl/vulkan): Fix tessellation clockwise parameter
2022-10-13 20:12:31 -04:00
liamwhite 048d3e2404 Merge pull request #9039 from Kelebek1/auto_backend
Auto select the SDL audio backend when Cubeb latency is too high
2022-10-13 20:12:22 -04:00
liamwhite 3c925a7282 Merge pull request #9032 from liamwhite/stub-friends
IFriendService: stub CheckFriendListAvailability
2022-10-13 20:12:08 -04:00
Mai e37d00332c Merge pull request #9065 from liamwhite/result-mess
result: enforce reference check specialization
2022-10-13 19:54:10 +00:00
Morph d3114c620d renderer_(opengl/vulkan): Fix tessellation clockwise parameter
This should be assigned CW only on Triangles_CW rather than not Triangles_CCW, making CCW the default winding order rather than CW.
2022-10-13 15:52:56 -04:00
Narr the Reg 26b76d2eaf Merge pull request #9066 from Morph1984/fix-stretch-to-window
settings: Update aspect_ratio range
2022-10-13 13:00:07 -05:00
Morph e2164f3417 settings: Update aspect_ratio range
Since 16:10 was added, the maximum value is now 4.
2022-10-13 12:24:04 -04:00
Liam c0fb5e876d result: enforce reference check specialization 2022-10-13 12:10:39 -04:00
bunnei 64c2ccb0cb Merge pull request #9034 from liamwhite/result-macros
kernel: add expanded result macros
2022-10-12 17:11:07 -07:00
bunnei dbacb31f61 Merge pull request #9027 from yuzu-emu/revert-8987-another-name-for-reinforcement-steel
Revert "vulkan: automatically use larger staging buffer sizes when possible"
2022-10-12 15:36:56 -07:00
bunnei 0b9f2c2f14 Merge pull request #9040 from liamwhite/woe-thirty-two
core_timing: use high-precision sleeps on non-Windows targets
2022-10-12 15:35:06 -07:00
bunnei e158167139 Merge pull request #9024 from liamwhite/async-screenshot
video_core: don't block rendering on screenshots
2022-10-12 13:26:32 -07:00
bunnei 3da4280e81 Merge pull request #9047 from german77/steam-aspect
yuzu: Add 16:10 aspect ratio
2022-10-12 12:54:23 -07:00
bunnei 77177a7e33 Merge pull request #9049 from liamwhite/monkeyhawk
syncpoint_manager: ensure handle is removable before removing
2022-10-12 12:34:22 -07:00
liamwhite 133a68ee9b Merge pull request #9048 from Kelebek1/regs
[video_core] Fix stencil mask registers
2022-10-11 17:22:40 -04:00
Liam b1cd6cec19 syncpoint_manager: ensure handle is removable before removing 2022-10-10 19:22:26 -04:00
liamwhite d9336860d7 Merge pull request #9044 from lat9nq/mingw-gcc-revert
ci/windows: Revert to using GCC for MinGW builds
2022-10-10 19:04:02 -04:00
Kelebek1 4496030ea9 Fix stencil func registers, make clip control equivalent to how it was before, but surely wrong. 2022-10-10 20:59:57 +01:00
Narr the Reg eb74ef474b yuzu: Add 16:10 aspect ratio 2022-10-10 13:32:33 -05:00
lat9nq 682c50715c ci/windows: Revert to using GCC for MinGW builds
Using MinGW in the future may not be ideal as it does not work very well
with crash dumps (#8682).

Switch back to GCC on MinGW. This also gives CI a way to check GCC 12
(as of writing, or whatever version of mingw-gcc Arch happens to be
shipping on a given week).
2022-10-09 17:47:52 -04:00
liamwhite c3cae9d992 Merge pull request #9043 from german77/vector_data
input_common: have an unique vector in callback status
2022-10-09 17:46:45 -04:00
german77 224a19758e input_common: have an unique vector in callback status 2022-10-09 12:49:18 -05:00
Kelebek1 8c9e238a7b Choose the SDL audio backend when Cubeb reports too high of a latency 2022-10-09 13:47:59 +01:00
Fernando S 55e6d0dae0 Merge pull request #8766 from Kelebek1/regs
[video_core] Update 3D registers
2022-10-09 07:04:03 +02:00
Liam 9632434243 core_timing: use high-precision sleeps on non-Windows targets 2022-10-08 18:27:40 -04:00
Mai ec9550ced5 Merge pull request #9033 from liamwhite/stub-fsp
fsp_srv: stub GetCacheStorageSize
2022-10-08 16:33:13 -04:00
Liam 47a2efee73 kernel: add expanded result macros 2022-10-08 12:41:27 -04:00
Liam 5b7c0f13d3 fsp_srv: stub GetCacheStorageSize 2022-10-08 12:24:00 -04:00
Liam ddf64e56af IFriendService: stub CheckFriendListAvailability 2022-10-07 22:19:41 -04:00
Mai 155213484b Merge pull request #9016 from liamwhite/drunken-schedule
vk_scheduler: wait for command processing to complete
2022-10-07 20:27:16 -04:00
Mai b7ad83383f Merge pull request #8932 from abouvier/cmake-pkgconfig
cmake: Fix FindPkgConfig
2022-10-07 20:25:51 -04:00
Mai 6f101e0f02 Merge pull request #9030 from Morph1984/api-disable
configure_graphics: Fix graphics API selection when a game is running
2022-10-07 20:25:23 -04:00
liamwhite 972b93bf00 Merge pull request #8807 from Docteh/default_fonts
Qt: work around Qt5's font choice for Chinese (in Windows)
2022-10-07 17:39:39 -04:00
Liam a5476541f2 video_core: don't block rendering on screenshots 2022-10-07 17:33:59 -04:00
Morph 1e35ade1ec configure_graphics: Fix graphics API selection when a game is running
The graphics API setting should not be changed when a game is running.
2022-10-07 15:11:26 -04:00
Narr the Reg b8777b6653 Merge pull request #9028 from liamwhite/wtype-limits
nfp_types: silence -Wtype-limits
2022-10-07 09:03:35 -05:00
Kelebek1 752659aef3 Update 3D regs 2022-10-07 14:13:45 +01:00
Liam 9574429c5f nfp_types: silence -Wtype-limits 2022-10-07 06:52:28 -04:00
liamwhite 20cf09471a Revert "vulkan: automatically use larger staging buffer sizes when possible" 2022-10-07 04:49:08 -04:00
bunnei 61883d8820 Merge pull request #6142 from lat9nq/prog_meta_ref_bind_address
program_metadata: Avoid reference binding to misaligned address
2022-10-06 20:42:15 -07:00
bunnei bb86fc573f Merge pull request #8944 from Tachi107/patch-2
build(room): simplify yuzu-room installation
2022-10-06 16:59:04 -07:00
Fernando S 1effa578f1 Merge pull request #8467 from FernandoS27/yfc-rel-1
Project yuzu Fried Chicken (Y.F.C.) Part 1
2022-10-06 21:29:53 +02:00
Byte df6dffa30b vulkan_blitter: Fix pool allocation double free. 2022-10-06 21:00:54 +02:00
Liam aedd739631 maxwell_dma: remove warnings from implemented functionality 2022-10-06 21:00:54 +02:00
Fernando Sahmkow ca3db0d7c9 General: address feedback 2022-10-06 21:00:54 +02:00
Liam 0d99b7962d state_tracker: workaround channel setup for homebrew 2022-10-06 21:00:54 +02:00
Liam c80ed6d81f general: rework usages of UNREACHABLE macro 2022-10-06 21:00:54 +02:00
Morph 903705043d nvdisp: End system frame after requesting to swap buffers
Fixes frametime reporting
2022-10-06 21:00:54 +02:00
Morph 11e1cbbdbd address_space: Rename va_start to virt_start
Avoids conflicting with the va_start macro
2022-10-06 21:00:54 +02:00
Morph fa342cae22 address_space: Address feedback 2022-10-06 21:00:54 +02:00
Morph fedd983f96 general: Format licenses as per SPDX guidelines 2022-10-06 21:00:54 +02:00
Fernando Sahmkow d97d409647 NvHostChannels: improve hack for supporting multiple channels. 2022-10-06 21:00:54 +02:00
Fernando Sahmkow c2b7de66b3 Address Feedback from bylaws. 2022-10-06 21:00:53 +02:00
Fernando Sahmkow 8a372035db Nvflinger: correct duplication. 2022-10-06 21:00:53 +02:00
VonChenPlus 9982cff98b Core: Fix get nvmap object random crash 2022-10-06 21:00:53 +02:00
Fernando Sahmkow fe24c65153 General: Fix clang format. 2022-10-06 21:00:53 +02:00
Fernando Sahmkow 1a9b71b1c6 Common: Fix variable shadowing. 2022-10-06 21:00:53 +02:00
Fernando Sahmkow cdce7f781b Vulkan Swapchain: Overall improvements. 2022-10-06 21:00:53 +02:00
Fernando Sahmkow 8d774e7415 NvDec: Fix regressions. 2022-10-06 21:00:53 +02:00
Fernando Sahmkow ada09778d9 Vulkan Texture Cache: Limit render area to the max width/height of the targets. 2022-10-06 21:00:53 +02:00
Fernando Sahmkow 8fd1d769fe ImageBase: Basic fixes. 2022-10-06 21:00:53 +02:00
Liam White afab6c143c General: Fix compilation for GCC 2022-10-06 21:00:53 +02:00
Fernando Sahmkow fd7afda1e8 VideoCore: Implement formats needed for N64 emulation. 2022-10-06 21:00:53 +02:00
Fernando Sahmkow 770e19f51a Buffer Cache: Deduce vertex array limit from memory layout when limit is the highest possible. 2022-10-06 21:00:53 +02:00
Fernando Sahmkow 8bb604b3be VideoCore: Add option to dump the macros. 2022-10-06 21:00:53 +02:00
Fernando Sahmkow a9ca39f859 NVDRV: Further improvements. 2022-10-06 21:00:53 +02:00
Fernando Sahmkow b59ca4df0c Buffer Cache: Basic fixes. 2022-10-06 21:00:53 +02:00
Fernando Sahmkow 98317f2b77 Decoders: Improve overall speed. 2022-10-06 21:00:53 +02:00
bunnei f5fd6b5c86 DMA & InlineToMemory Engines Rework. 2022-10-06 21:00:53 +02:00
Fernando Sahmkow b2099fbdcc Maxwell3D: Add small_index_2 2022-10-06 21:00:53 +02:00
Fernando Sahmkow 7cfa28a666 Memory Manager: ensure safety of GPU to CPU address. 2022-10-06 21:00:53 +02:00
Fernando Sahmkow 5a568b1655 MemoryManager: Fix errors popping out. 2022-10-06 21:00:53 +02:00
Fernando Sahmkow 3d02143476 Shader Decompiler: implement better tracking for Vulkan samplers. 2022-10-06 21:00:53 +02:00
Fernando Sahmkow ba34cf0a69 Shader Decompiler: Check for shift when deriving composite samplers. 2022-10-06 21:00:52 +02:00
Fernando Sahmkow a283eda320 Shader Decompiler: Fix dangerous behavior of invalid iterator insertion. 2022-10-06 21:00:52 +02:00
Fernando Sahmkow 359f22b808 MemoryManager: Finish up the initial implementation. 2022-10-06 21:00:52 +02:00
Fernando Sahmkow 5caa150e9a OpenGL: Fix TickWork 2022-10-06 21:00:52 +02:00
Fernando Sahmkow bc8b3d225e VideoCore: Refactor fencing system. 2022-10-06 21:00:52 +02:00
Fernando Sahmkow 4d60410dd9 MemoryManager: initial multi paging system implementation. 2022-10-06 21:00:52 +02:00
Fernando Sahmkow 98b5e236d4 Vulkan: Fix Scissor on Clears 2022-10-06 21:00:52 +02:00
Fernando Sahmkow 920429fde7 NVDRV: Further refactors and eliminate old code. 2022-10-06 21:00:52 +02:00
Fernando Sahmkow 2931101e6f NVDRV: Refactor Host1x 2022-10-06 21:00:52 +02:00
Fernando Sahmkow 668e80a9f4 VideoCore: Refactor syncing. 2022-10-06 21:00:52 +02:00
Fernando Sahmkow e44ac8b821 Texture Cache: Fix GC and GPU Modified on Joins. 2022-10-06 21:00:52 +02:00
Fernando Sahmkow f350c3d74e Texture cache: Fix the remaining issues with memory mnagement and unmapping. 2022-10-06 21:00:52 +02:00
Fernando Sahmkow 9cf4c8831d Texture cache: Fix dangling references on multichannel. 2022-10-06 21:00:52 +02:00
Fernando Sahmkow e462191482 Refactor VideoCore to use AS sepparate from Channel. 2022-10-06 21:00:52 +02:00
Fernando Sahmkow bb74973bba General: Rebase fixes. 2022-10-06 21:00:52 +02:00
Fernando Sahmkow 6fc4012396 VideoCore: Extra Fixes. 2022-10-06 21:00:52 +02:00
Fernando Sahmkow feb49c822d NVDRV: Remake ASGPU 2022-10-06 21:00:52 +02:00
Fernando Sahmkow c6ea0c650e NVDRV: Update copyright notices. 2022-10-06 21:00:52 +02:00
Fernando Sahmkow 0f4ae3cc52 MemoryManager: Temporary Fix for NVDEC. 2022-10-06 21:00:52 +02:00
Fernando Sahmkow 835b950f7e NvHostCtrl: Fix merge of nvflinger. 2022-10-06 21:00:52 +02:00
Fernando Sahmkow cbaf3fb433 VideoCore: Update MemoryManager 2022-10-06 21:00:51 +02:00
Fernando Sahmkow b617874724 Common: implement MultiLevelPageTable. 2022-10-06 21:00:51 +02:00
Fernando Sahmkow 3f8e7a5585 VideoCore: Fix channels with disk pipeline/shader cache. 2022-10-06 21:00:51 +02:00
Fernando Sahmkow d7990c159e OpenGl: Implement Channels. 2022-10-06 21:00:51 +02:00
Fernando Sahmkow 2c62563ab5 NVHOST_CTRl: Implement missing method and fix some stuffs. 2022-10-06 21:00:51 +02:00
Fernando Sahmkow 139ea93512 VideoCore: implement channels on gpu caches. 2022-10-06 21:00:51 +02:00
Fernando Sahmkow c77b8df12e NVASGPU: Fix Remap. 2022-10-06 21:00:51 +02:00
Fernando Sahmkow ad038609c8 NVDRV: Fix clearing when destroying. 2022-10-06 21:00:51 +02:00
Fernando Sahmkow 68d9504a04 NVMAP: Fix the Free return parameters. 2022-10-06 21:00:51 +02:00
Fernando Sahmkow af35dbcf63 NVDRV: Fix Open/Close and make sure each device is correctly created. 2022-10-06 21:00:51 +02:00
Fernando Sahmkow de0e8eff42 NVDRV: Implement new NvMap 2022-10-06 21:00:51 +02:00
Fernando Sahmkow 3cbe352c18 NVDRV: Refactor and add new NvMap. 2022-10-06 21:00:51 +02:00
Fernando Sahmkow a21b8824fb NVDRV: Cleanup. 2022-10-06 21:00:51 +02:00
Fernando Sahmkow d30b885d71 NVDRV: Implement QueryEvent. 2022-10-06 21:00:51 +02:00
Fernando Sahmkow 39a5ce4e69 NvHost: Remake Ctrl Implementation. 2022-10-06 21:00:51 +02:00
Fernando Sahmkow ac104a24d1 NvHost: Try a different approach to blocking. 2022-10-06 21:00:51 +02:00
Fernando Sahmkow 7b7f6f1cb7 NvHost: Fix some regressions and correct signaling on timeout. 2022-10-06 21:00:51 +02:00
Fernando S 31d4bc6953 Merge pull request #9025 from FernandoS27/slava-ukrayini
Texture Cache: Add ASTC 10x5 Format.
2022-10-06 17:10:28 +02:00
Fernando Sahmkow 1a49991676 Texture Cache: Add ASTC 10x5 Format. 2022-10-06 16:45:40 +02:00
bunnei d55096ce85 Merge pull request #9013 from liamwhite/spinning-a-yarn
common: remove "yuzu:" prefix from thread names
2022-10-05 18:53:42 -07:00
bunnei 1689530f52 Merge pull request #9015 from german77/amiibo-rewrite
service: nfp: Fix errors to pass unit testing
2022-10-05 14:13:57 -07:00
Kyle Kienapfel 3b5a937125 Show error from cpp-httplib when we don't have a response to read (report errors while connecting to API) (#8999)
Co-authored-by: Kyle Kienapfel <Docteh@users.noreply.github.com>
2022-10-05 21:39:54 +02:00
Fernando S 71fe9fd0f2 Merge pull request #8987 from liamwhite/another-name-for-reinforcement-steel
vulkan: automatically use larger staging buffer sizes when possible
2022-10-05 08:54:22 +02:00
Fernando S 4774e32593 Merge pull request #9011 from liamwhite/frog-emoji-moment
shader_recompiler: add extended LDC to GLASM backend
2022-10-05 08:53:26 +02:00
bunnei fc0ace6048 Merge pull request #9005 from liamwhite/micro-fit
macro_jit_x64: cancel exit for taken branch
2022-10-04 20:08:02 -07:00
bunnei 92c0ad23eb Merge pull request #9010 from liamwhite/buttwise
macro_jit_x64: fix miscompilation of bit extraction operations
2022-10-04 15:52:39 -07:00
Liam 7969d4d5de vk_scheduler: wait for command processing to complete 2022-10-03 20:03:25 -04:00
Narr the Reg e85c19adcb service: nfp: Fix errors to pass unit testing 2022-10-03 18:06:55 -05:00
Liam 35d3e7db2a common: remove "yuzu:" prefix from thread names 2022-10-03 18:43:56 -04:00
Liam ae7062d522 shader_recompiler: add extended LDC to GLASM backend 2022-10-02 17:32:54 -04:00
bunnei 61399de5db Merge pull request #8955 from german77/amiibo-rewrite
core: nfp: Rewrite implementation to remove direct access from the frontend
2022-10-02 14:28:43 -07:00
german77 1485daff06 service: mii: Copy only valid name bytes 2022-10-02 12:34:24 -05:00
Narr the Reg d9d566bd3f service: nfp: Implement mount target and open application area errors, minor fixes 2022-10-02 12:34:14 -05:00
german77 673de3995b nfp: Multiple fixes against HW 2022-10-02 12:32:26 -05:00
german77 3ce0ef04dd service: nfp: address comments 2022-10-02 12:32:26 -05:00
german77 afea5c163f service: nfp: Rewrite and implement applet calls 2022-10-02 12:32:26 -05:00
german77 8a3d22c4bd core: hid: Add nfc support to emulated controller 2022-10-02 12:32:26 -05:00
german77 f6d57d7dd9 yuzu: Use virtual amiibo driver instead of nfp service 2022-10-02 12:32:26 -05:00
german77 da8864d002 input_common: Enable virtual amiibo driver 2022-10-02 12:32:26 -05:00
german77 e8d71712e7 input_common: Create virtual amiibo driver 2022-10-02 12:32:26 -05:00
bunnei 80a3a73123 Merge pull request #8992 from Morph1984/vi-vsync-event
service: vi: Retrieve vsync event once per display
2022-10-02 03:02:59 -07:00
liamwhite 188932768e Merge pull request #6598 from FernandoS27/falklands-are-british
MacroHLE: Add MultidrawIndirect HLE Macro.
2022-10-01 20:58:03 -04:00
Fernando Sahmkow a60b669ef4 MacroHLE: Add MultidrawIndirect HLE Macro. 2022-10-01 20:57:00 -04:00
Liam 1225627515 macro_jit_x64: fix miscompilation of bit extraction operations 2022-10-01 20:31:21 -04:00
Kyle Kienapfel 1dba5fab62 Qt: work around Qt5's font choice for Chinese
On Windows there are currently two fonts used.

The first, does the Menu, QTreeView and Tooltips
Second is Everything else which is a default font.

From inspecting QApplication::font() at runtime
Windows 10 English: QFont(MS Shell Dlg 2,8.25,-1,5,50,0,0,0,0,0)
Windows 11 Japanese:        MS UI Gothic,9   ,-1,5,50,0,0,0,0,0
Windows 11 Traditional Chinese: PMingLiU,9   ,-1,5,50,0,0,0,0,0
Windows 11 Simplified Chinese:    SimSun,9   ,-1,5,50,0,0,0,0,0
Windows 11 Korean:                 Gulim,9   ,-1,5,50,0,0,0,0,0

I initially investigated dynamically changing the font when
the UI language is English, but this was getting quite messy

Qt6 makes changes to default font in some situations, so this
PR is being narrowed in scope to only effect Chinese font choices.
This change only effects rendering of Latin/Cyrillic characters.
2022-10-01 15:27:23 -07:00
bunnei 2a752bbd64 Merge pull request #8876 from FearlessTobi/multiplayer-part3
ldn: Implement "local wireless" networked multiplayer
2022-10-01 14:53:36 -07:00
liamwhite 001168d191 Merge pull request #9009 from yuzu-emu/bunnei-move-deploy-linux.sh
Migrate deploy-linux.sh from lat9nq's repo.
2022-10-01 16:57:46 -04:00
Narr the Reg 181a54a37b Merge pull request #9008 from ZwipZwapZapony/controller.colors_state.right
Fix "controller.colors_state.right" being "left"
2022-10-01 14:37:55 -05:00
bunnei 4242064560 Merge pull request #8874 from vonchenplus/align_index_buffer_size
Align index buffe size when vertex_buffer_unified_memory enable
2022-10-01 10:28:50 -07:00
bunnei 700f1d498e Migrate deploy-linux.sh from lat9nq's repo. 2022-10-01 10:25:28 -07:00
Zwip-Zwap Zapony 31e3437a2f Fix "controller.colors_state.right" being "left" 2022-10-01 18:18:08 +02:00
Mai 2213927253 Merge pull request #9004 from zhaobot/tx-update-20221001041028
Update translations (2022-10-01)
2022-10-01 07:37:24 -04:00
Liam b80f7faebe macro_jit_x64: cancel exit for taken branch 2022-10-01 01:32:24 -04:00
The yuzu Community 4b40799e03 Update translations (2022-10-01) 2022-10-01 04:10:52 +00:00
bunnei d9e375acc3 Merge pull request #8910 from vonchenplus/astc_decode_error
video_core: Modify astc texture decode error fill value
2022-09-30 15:34:11 -07:00
bunnei dbb9d601df Merge pull request #8934 from german77/palma_release
service: hid: Partially implement palma controller
2022-09-29 12:48:28 -07:00
Morph 2e3aad41aa Merge pull request #8993 from lat9nq/drop-linuxdeploy
ci/linux: Drop linuxdeploy usage
2022-09-28 20:10:47 -04:00
bunnei 9015a512c2 Merge pull request #8940 from german77/silence
yuzu: Silence some clang warnings
2022-09-28 14:37:23 -07:00
Morph 0f6007b405 Merge pull request #8989 from merryhime/loader-nullptr
core/loader: Return nullptr if file is nullptr
2022-09-27 10:59:46 -04:00
lat9nq ad9f97cd8d ci/linux: Drop linuxdeploy usage
Recent versions of Docker appear to cause the Qt linuxdeploy plugin to
throw a boost file copy error.

This switches from linuxdeploy to a script of mine I've been working on
for a while.
2022-09-26 00:35:03 -04:00
Morph 41e855bd42 service: vi: Retrieve vsync event once per display
The display vsync event can only be retrieved once per display. Returns VI::ResultPermissionDenied if we attempt to retrieve the vsync event for the same display.

Prevents games such as .hack//G.U. Last Recode from consuming all the handles in the handle table by spamming vsync event retrievals and allows it to go in game.
2022-09-25 21:33:36 -04:00
Morph acc887cc34 service: vi: Move VI results into its own file 2022-09-25 20:33:25 -04:00
Merry f55ed1cab0 core/loader: Return nullptr if file is nullptr 2022-09-25 19:31:35 +01:00
Liam 087c6c2ef1 vulkan: automatically use larger staging buffer sizes when possible 2022-09-25 02:28:03 -04:00
bunnei 465c46387d Merge pull request #8920 from abouvier/cmake-git
cmake: fix git detection
2022-09-24 23:11:45 -07:00
Narr the Reg 23589ad9b8 service: hid: Partially implement palma controller 2022-09-25 00:13:12 -05:00
bunnei 1b1b99fbd5 Merge pull request #8941 from Kelebek1/single_core_sucks
Do not try to pause core timing from the audio thread when using single-core
2022-09-23 22:40:30 -07:00
Morph d794ced303 Merge pull request #8945 from Tachi107/typos
chore: fix some typos
2022-09-23 20:28:43 -04:00
Morph 5082efef6c Merge pull request #8948 from german77/order
yuzu: sort input profiles by name
2022-09-23 20:28:35 -04:00
Morph 86ccc87111 Merge pull request #8933 from lat9nq/ci-use-apprun-sh
ci/linux: Use AppRun.sh to start AppImage
2022-09-23 20:28:28 -04:00
Morph 12baf88dc8 Merge pull request #8930 from lat9nq/disable-vulkan-check
yuzu qt: Add option to disable startup Vulkan check
2022-09-23 20:28:13 -04:00
Narr the Reg f711d1ce52 yuzu: sort input profiles by name 2022-09-23 12:31:35 -05:00
Morph 70abb13a43 Merge pull request #8943 from lioncash/netiface
sockets: Make fd member variable protected
2022-09-23 09:08:07 -04:00
Morph c2c3f2c3e7 Merge pull request #8939 from lioncash/render
audio_renderer: Make GetCommandBuffer() take a u32
2022-09-23 09:07:52 -04:00
Morph 3b77dec188 Merge pull request #8938 from lioncash/manager
audio_manager: Minor cleanup related changes
2022-09-23 09:07:38 -04:00
Andrea Pappacoda 4a493cb10f chore: fix some typos
Fix some typos reported by Lintian
2022-09-23 13:38:23 +02:00
Andrea Pappacoda db88eaa346 build(room): simplify yuzu-room installation
CMake is able to automatically install binaries in the correct location. Also see my older patch, https://github.com/yuzu-emu/yuzu/commit/af94bf4a594b6a3599fae1d78e5d283b9f602032

Cc: @FearlessTobi
2022-09-22 21:51:56 +02:00
Lioncash c8da75b7ed sockets: Make fd member variable protected
Other things shouldn't be able to directly mess around with the
descriptor
2022-09-22 08:20:54 -04:00
Kelebek1 56b8a9ba6e Do not try to pause core timing from the audio thread when using single-core 2022-09-22 01:23:57 +01:00
Narr the Reg 5a74ced59a yuzu: Silence some clang warnings 2022-09-21 11:51:31 -05:00
Lioncash c891497b61 audio_renderer: Make GetCommandBuffer() take a u32
This function is only ever called with unsigned types, and all of the
other interface functions take session_id as a u32, so this makes the
class a little more consistent.
2022-09-21 10:00:57 -04:00
Lioncash 00616c7ad8 audio_manager: Forward declare result type
Moves the include into the cpp file to lessen header dependencies.
2022-09-21 09:43:59 -04:00
Lioncash 75d6fe3669 audio_manager: Remove redundant cast in ThreadFunc()
We can just use a local here to get rid of a second cast.
2022-09-21 09:35:22 -04:00
Lioncash e48e22eb52 audio_manager: move std::functions in SetOutManager/SetInManager
Prevents unnecessary reallocations in the event the captured variables
are larger than the internal std::function buffer.
2022-09-21 09:32:15 -04:00
Lioncash da0fd51642 audio_manager: Remove unused forward declarations
Allows us to get rid of some unnecessary forward declarations and
includes.
2022-09-21 09:29:35 -04:00
Lioncash 08d81e0bd8 audio_manager: Remove unused sessions_started member variable
This isn't used, so it can be removed.
2022-09-21 09:28:05 -04:00
Lioncash b59b967280 audio_manager: Remove dependence on system state
This isn't used by the class, so this can be removed for the time being.
2022-09-21 09:26:42 -04:00
lat9nq 37b4f79b54 ci/linux: Use AppRun.sh to start AppImage
The current AppRun is more difficult to update. This script still
uses the old version of AppImageKit-checkrt, but now we use the shell
script version so we can set our own environment variables as the
application starts up.

This specific version searches for and sets the correct root CA file to
prevent SSL errors in yuzu.
2022-09-20 18:57:27 -04:00
Alexandre Bouvier 09a87966e0 cmake: Fix FindPkgConfig 2022-09-20 22:21:52 +02:00
FearlessTobi 4213f1c126 Address some review comments 2022-09-20 19:36:32 +02:00
bunnei 8d4458ef24 Merge pull request #8849 from Morph1984/parallel-astc
astc: Enable parallel CPU astc decoding
2022-09-19 12:17:51 -07:00
lat9nq 89af4bfba8 yuzu qt: Add option to disable startup Vulkan check
The startup check apparently confuses other programs when yuzu launches
2 processes and then quickly closes one of them. Though this isn't
really our issues it's also not a big deal for me to add an option to
work around that issue.
2022-09-19 14:46:12 -04:00
bunnei 3a5f9409c8 Merge pull request #8915 from vonchenplus/opus_multi_stream
core: implement HwOpus GetWorkBufferSizeForMultiStreamEx
2022-09-17 16:07:33 -07:00
Alexandre Bouvier 7239470dad cmake: fix git detection 2022-09-18 00:04:35 +02:00
bunnei 7172339c7a Merge pull request #8827 from german77/amiibo_release
core: nfp: Implement amiibo encryption
2022-09-17 11:11:21 -07:00
bunnei 9c32f29af1 Merge pull request #8650 from Kelebek1/vsync
[Coretiming/NVNFlinger] Improve multi-core vsync timing, and core timing accuracy
2022-09-17 11:10:54 -07:00
bunnei 4a7a771340 Merge pull request #8914 from lioncash/audio-const
audio_core: Mark several member functions as const
2022-09-16 23:51:31 -07:00
bunnei eb726677b2 Merge pull request #8916 from Docteh/muilti_build
GIT: Modify .gitignore to ignore wildcard for build directories
2022-09-16 18:19:01 -07:00
bunnei 92813f01a4 Merge pull request #8906 from Docteh/fix_icons
UI: move icons from default into colorful theme.
2022-09-16 18:12:04 -07:00
Kyle K 49870baea4 GIT: Modify .gitignore to ignore wildcard for build directories
Helps if you have multiple build folders. There are other, dark ways to
hide extra build folders from git, but this is better.

See: https://github.com/citra-emu/citra/pull/6130
2022-09-16 10:58:29 -07:00
Morph 344006b856 Merge pull request #8869 from SachinVin/cmake
core/CMakeLists.txt: Remove duplicate files.
2022-09-16 13:11:33 -04:00
Morph 8dafe15600 Merge pull request #8649 from lat9nq/common-position-independent
common: Use PROJECT_SOURCE_DIR to find CMakeModules
2022-09-16 12:48:53 -04:00
Morph 44ccec7846 Merge pull request #8682 from lat9nq/dumpy
yuzu qt: Add option to create Windows crash dumps
2022-09-16 12:47:51 -04:00
Morph 882dfa36ae Merge pull request #6667 from lat9nq/ea-appimage
ci,linux: Support Patreon releases
2022-09-16 12:47:38 -04:00
FengChen 672e61d802 core: implement HwOpus GetWorkBufferSizeForMultiStreamEx 2022-09-17 00:28:56 +08:00
Morph 60aa942210 Merge pull request #8911 from lioncash/cexpr-string
audio_device: Make AudioDeviceName constructor constexpr
2022-09-16 10:18:58 -04:00
Morph 809126c94a astc: Enable parallel CPU astc decoding
Given the issues with GPU accelerated ASTC decoding with NVIDIA's latest drivers, parallelize astc decoding on the CPU.
Uses half the available threads in the system for astc decoding.
2022-09-16 10:16:42 -04:00
Lioncash 7e3cdfc453 audio_renderer: Pass command buffer by const reference
This is just being copied and isn't modified at all.
2022-09-16 10:06:53 -04:00
Lioncash d5d6322640 sink_stream: Mark GetQueueSize as const 2022-09-16 10:00:52 -04:00
Lioncash 6b1cb73350 node_states: Mark relevant member functions as const 2022-09-16 09:59:56 -04:00
Lioncash e4bc7b8611 i3dl2/reverb: Mark relevant member functions as const
These two don't modify member state.
2022-09-16 09:58:49 -04:00
Lioncash b2c2138af7 behavior_info: Mark CopyErrorInfo as const
This doesn't modify member state.

We can also mark the parameter of AppendError as const as well, since it
isn't modified.
2022-09-16 09:55:17 -04:00
Lioncash b862d5d8d8 audio_device: Mark GetDeviceVolume as const
This doesn't modify instance state.
2022-09-16 09:52:34 -04:00
Lioncash 36c77761cf audio_render_manager: Mark several functions as const 2022-09-16 09:50:32 -04:00
Lioncash 7a5d235d94 audio_in: Mark several functions as const
These functions don't modify class state, so we can mark them as such
2022-09-16 09:45:54 -04:00
Lioncash d1f3c121a0 audio_out: Mark several functions as const
These don't affect class state, so we can mark them as such.
2022-09-16 09:45:51 -04:00
Lioncash e9109cb5f2 audio_buffers: Pass by const-ref in AppendBuffers
This function doesn't modify the passed in buffer, so we can make that
explicit.
2022-09-16 09:36:03 -04:00
Lioncash cb2a33babc device_session: Convert for loop into ranged for in AppendBuffers
Simplifies the indexing code a little bit.
2022-09-16 09:32:57 -04:00
Lioncash a278fa6e2a device_session: Pass arguments by const-ref in relevant functions
These functions don't modify the passed in audio buffers, so we can
signify that in the interface.
2022-09-16 09:31:33 -04:00
Lioncash d55046c5e9 audio_device: Mark member functions as const where applicable
These member functions don't modify any internal state.
2022-09-15 09:06:17 -04:00
Lioncash 1c7dae966d audio_device: Make AudioDeviceName constructor constexpr
These are used as read-only arrays, so we can make the data read-only
and available at compile-time.

Now constructing an AudioDevice no longer needs to initialize some
tables
2022-09-15 09:03:40 -04:00
FengChen 88007077e2 video_core: Modify astc texture decode error fill value 2022-09-15 17:04:44 +08:00
liushuyu aa11d73bba dedicated_room: fix token padding ...
... mebedtls' base64 routine has a strange behavioral issue where if the
input is invalid, it will not report it as invalid, but rather returning
a bunch of garbage data. This new round-tripping padding method should
eliminate such issue.
2022-09-10 18:56:29 -05:00
Narr the Reg 1694c55d62 fix black icon 2022-09-10 18:56:06 -05:00
german77 8f207bd93d yuzu: Multiple room UI improvements 2022-09-10 19:39:25 +02:00
FengChen 92b1f8d5da Align index buffe size when vertex_buffer_unified_memory enable 2022-09-10 20:01:33 +08:00
FearlessTobi f5e635adda ldn: Initial implementation 2022-09-09 14:30:22 +02:00
SachinVin 9c6cd93195 core/CMakeLists.txt: Remove duplicate files. 2022-09-08 22:03:53 +05:30
german77 063b23cc58 core: nfp: Remove magic numbers 2022-09-07 09:49:43 -05:00
german77 4834961736 core: nfp: Workaround for lack of multiple nfp interfaces 2022-09-07 01:04:00 -05:00
Narr the Reg caa138b33f core: nfp: Correct date and amiibo name 2022-09-07 01:04:00 -05:00
Narr the Reg 19a4e12e6e core: nfp: Implement Convert and RecreateApplicationArea, accuracy fixes 2022-09-07 01:04:00 -05:00
german77 848f69eb19 core: nfp: Implement amiibo encryption 2022-09-07 01:04:00 -05:00
lat9nq 9dc9e501de ci/windows: Upload debugging symbols 2022-09-04 21:36:35 -04:00
lat9nq 12f7d42d32 mini_dump: Address review feedback
Uses fmt::print as opposed to std::fprintf. Adds a missing return.
static's a single-use function. Initializes structs as opposed to
std::memset where possible. Fixes CMake linkage.

Co-authored-by: Lioncash <mathew1800@gmail.com>

mini_dump: Use a namespace

Co-authored-by: Lioncash <mathew1800@gmail.com>
2022-09-04 21:36:35 -04:00
lat9nq 45b343d1d0 ci,workflows: Enable crash dumps on MSVC builds
ci/windows: Enable crash dumps on MinGW builds
2022-09-04 21:36:34 -04:00
lat9nq c976613ab2 vcpkg,cmake: Use vcpkg for dbghelp 2022-09-04 21:36:05 -04:00
lat9nq e339ec0e00 mini_dump: Check for debugger before spawning a child
mini_dump: Clean up

mini_dump: Fix MSVC error

mini_dump: Silence MSVC warning C4700

Zero initialize deb_ev.

mini_dump: Add license info
2022-09-04 21:36:05 -04:00
lat9nq 3dbaafe1f3 mini_dump: Cleanup and add comments
Removes some unnecessary code.

wip
2022-09-04 21:36:05 -04:00
lat9nq f958cbc737 yuzu: Use a debugger to generate minidumps
yuzu: Move mini_dump out of core

startup_checks: Better exception handling
2022-09-04 21:36:04 -04:00
Morph 606cdb17d3 core_timing: Sleep in discrete intervals, yield during spin 2022-08-02 01:01:54 -04:00
Kelebek1 658e1ee426 Add missing looping event schedule signal 2022-08-02 01:01:54 -04:00
Kelebek1 83a24ad638 Make coretiming waiting more accurate 2022-08-02 01:01:54 -04:00
Kelebek1 9d3b190465 Rework multi-core vsync 2022-08-01 23:51:53 -04:00
lat9nq 260430c849 common: Use PROJECT_SOURCE_DIR to find CMakeModules
Fixes CMake configuration when yuzu is a submodule of another project.
2022-08-01 23:18:56 -04:00
lat9nq 6b58db9ccd patreon step2: Use jobs to build for Windows and Linux
Apparently the two stages were not building in parallel. Specify
individual jobs that run MSVC and Linux building instead.
2022-07-31 21:07:46 -04:00
lat9nq d77fe3b1c2 ci/linux: EA AppImage adjustments
Prevent AppImageLauncher from trying to integrate our AppImage on end
user systems. Don't include the basic yuzu executable with EA or
Mainline.
2022-07-31 03:25:29 -04:00
lat9nq 69bd6cd490 patreon step2: Enable Linux build
I sure as heck don't know what I'm doing :)

patreon_step2: Fix caching

:limesDance: still don't know what I'm doing :limesDance:
2022-07-31 01:35:12 -04:00
lat9nq dc915aff62 ci,linux: Support Patreon releases
The Early Access AppImage needs to be accessible through liftinstall, so
a couple modifications need to made:

The DIR_NAME needs to not include the revision info.
The EA AppImage name cannot contain revision info.
The EA AppImage has to be packaged with the rest of the yuzu package,
which means both binaries and the source are bundled with it now in an
archive.

In addition, fix the source archive so yuzu can actually be built from
it.

upload: Copy AppImage to both mainline and EA release package
2022-07-31 01:35:11 -04:00
lat9nq bfb7cbc292 program_metadata: Unpack FileAccessHeader and FileAccessControl
Avoids a reference binding to a misaligned addresses. Unpacking one
requires unpacking the other, otherwise there'll be a misaligned address
on the leftover one.
2022-02-13 02:20:56 -05:00
381 changed files with 30018 additions and 18331 deletions
+6 -8
View File
@@ -33,16 +33,14 @@ DESTDIR="$PWD/AppDir" ninja install
rm -vf AppDir/usr/bin/yuzu-cmd AppDir/usr/bin/yuzu-tester
# Download tools needed to build an AppImage
wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/linuxdeploy-x86_64.AppImage
wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/linuxdeploy-plugin-qt-x86_64.AppImage
wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/AppRun-patched-x86_64
wget -nc https://raw.githubusercontent.com/yuzu-emu/ext-linux-bin/main/gcc/deploy-linux.sh
wget -nc https://raw.githubusercontent.com/yuzu-emu/AppImageKit-checkrt/old/AppRun.sh
wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/exec-x86_64.so
# Set executable bit
chmod 755 \
AppRun-patched-x86_64 \
deploy-linux.sh \
AppRun.sh \
exec-x86_64.so \
linuxdeploy-x86_64.AppImage \
linuxdeploy-plugin-qt-x86_64.AppImage
# Workaround for https://github.com/AppImage/AppImageKit/issues/828
export APPIMAGE_EXTRACT_AND_RUN=1
@@ -52,7 +50,7 @@ mkdir -p AppDir/usr/optional/libstdc++
mkdir -p AppDir/usr/optional/libgcc_s
# Deploy yuzu's needed dependencies
./linuxdeploy-x86_64.AppImage --appdir AppDir --plugin qt
DEPLOY_QT=1 ./deploy-linux.sh AppDir/usr/bin/yuzu AppDir
# Workaround for libQt5MultimediaGstTools indirectly requiring libwayland-client and breaking Vulkan usage on end-user systems
find AppDir -type f -regex '.*libwayland-client\.so.*' -delete -print
@@ -60,6 +58,6 @@ find AppDir -type f -regex '.*libwayland-client\.so.*' -delete -print
# Workaround for building yuzu with GCC 10 but also trying to distribute it to Ubuntu 18.04 et al.
# See https://github.com/darealshinji/AppImageKit-checkrt
cp exec-x86_64.so AppDir/usr/optional/exec.so
cp AppRun-patched-x86_64 AppDir/AppRun
cp AppRun.sh AppDir/AppRun
cp --dereference /usr/lib/x86_64-linux-gnu/libstdc++.so.6 AppDir/usr/optional/libstdc++/libstdc++.so.6
cp --dereference /lib/x86_64-linux-gnu/libgcc_s.so.1 AppDir/usr/optional/libgcc_s/libgcc_s.so.1
+19 -6
View File
@@ -5,21 +5,24 @@
. .ci/scripts/common/pre-upload.sh
APPIMAGE_NAME="yuzu-${GITDATE}-${GITREV}.AppImage"
REV_NAME="yuzu-linux-${GITDATE}-${GITREV}"
APPIMAGE_NAME="yuzu-${RELEASE_NAME}-${GITDATE}-${GITREV}.AppImage"
BASE_NAME="yuzu-linux"
REV_NAME="${BASE_NAME}-${GITDATE}-${GITREV}"
ARCHIVE_NAME="${REV_NAME}.tar.xz"
COMPRESSION_FLAGS="-cJvf"
if [ "${RELEASE_NAME}" = "mainline" ]; then
DIR_NAME="${REV_NAME}"
if [ "${RELEASE_NAME}" = "mainline" ] || [ "${RELEASE_NAME}" = "early-access" ]; then
DIR_NAME="${BASE_NAME}-${RELEASE_NAME}"
else
DIR_NAME="${REV_NAME}_${RELEASE_NAME}"
DIR_NAME="${REV_NAME}-${RELEASE_NAME}"
fi
mkdir "$DIR_NAME"
cp build/bin/yuzu-cmd "$DIR_NAME"
cp build/bin/yuzu "$DIR_NAME"
if [ "${RELEASE_NAME}" != "early-access" ] && [ "${RELEASE_NAME}" != "mainline" ]; then
cp build/bin/yuzu "$DIR_NAME"
fi
# Build an AppImage
cd build
@@ -32,6 +35,11 @@ if ! ./appimagetool-x86_64.AppImage --version; then
export APPIMAGE_EXTRACT_AND_RUN=1
fi
# Don't let AppImageLauncher ask to integrate EA
if [ "${RELEASE_NAME}" = "mainline" ] || [ "${RELEASE_NAME}" = "early-access" ]; then
echo "X-AppImage-Integrate=false" >> AppDir/org.yuzu_emu.yuzu.desktop
fi
if [ "${RELEASE_NAME}" = "mainline" ]; then
# Generate update information if releasing to mainline
./appimagetool-x86_64.AppImage -u "gh-releases-zsync|yuzu-emu|yuzu-${RELEASE_NAME}|latest|yuzu-*.AppImage.zsync" AppDir "${APPIMAGE_NAME}"
@@ -46,4 +54,9 @@ if [ -f "build/${APPIMAGE_NAME}.zsync" ]; then
cp "build/${APPIMAGE_NAME}.zsync" "${ARTIFACTS_DIR}/"
fi
# Copy the AppImage to the general release directory and remove git revision info
if [ "${RELEASE_NAME}" = "mainline" ] || [ "${RELEASE_NAME}" = "early-access" ]; then
cp "build/${APPIMAGE_NAME}" "${DIR_NAME}/yuzu-${RELEASE_NAME}.AppImage"
fi
. .ci/scripts/common/post-upload.sh
+2 -5
View File
@@ -10,17 +10,14 @@ set -e
ccache -sv
mkdir -p build && cd build
export LDFLAGS="-fuse-ld=lld"
# -femulated-tls required due to an incompatibility between GCC and Clang
# TODO(lat9nq): If this is widespread, we probably need to add this to CMakeLists where appropriate
export CXXFLAGS="-femulated-tls"
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE="${PWD}/../CMakeModules/MinGWClangCross.cmake" \
-DCMAKE_TOOLCHAIN_FILE="${PWD}/../CMakeModules/MinGWCross.cmake" \
-DDISPLAY_VERSION="$1" \
-DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON \
-DENABLE_QT_TRANSLATION=ON \
-DUSE_CCACHE=ON \
-DYUZU_CRASH_DUMPS=ON \
-DYUZU_USE_BUNDLED_SDL2=OFF \
-DYUZU_USE_EXTERNAL_SDL2=OFF \
-DYUZU_TESTS=OFF \
+2 -2
View File
@@ -65,8 +65,8 @@ if ("$env:GITHUB_ACTIONS" -eq "true") {
# None of the other GHA builds are including source, so commenting out today
#Copy-Item $MSVC_SOURCE_TARXZ -Destination "artifacts"
# Are debug symbols important?
# cp .\build\bin\yuzu*.pdb .\pdb\
# Debugging symbols
cp .\build\bin\yuzu*.pdb .\artifacts\
# Write out a tag BUILD_TAG to environment for the Upload step
# We're getting ${{ github.event.number }} as $env:PR_NUMBER"
+1 -1
View File
@@ -9,7 +9,7 @@ parameters:
steps:
- script: choco install vulkan-sdk
displayName: 'Install vulkan-sdk'
- script: refreshenv && mkdir build && cd build && cmake -G "Visual Studio 17 2022" -A x64 -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DYUZU_TESTS=OFF -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DDISPLAY_VERSION=${{ parameters['version'] }} -DCMAKE_BUILD_TYPE=Release .. && cd ..
- script: refreshenv && mkdir build && cd build && cmake -G "Visual Studio 17 2022" -A x64 -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DYUZU_TESTS=OFF -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DDISPLAY_VERSION=${{ parameters['version'] }} -DCMAKE_BUILD_TYPE=Release -DYUZU_CRASH_DUMPS=ON .. && cd ..
displayName: 'Configure CMake'
- task: MSBuild@1
displayName: 'Build'
+23 -2
View File
@@ -11,9 +11,30 @@ stages:
- stage: build
displayName: 'build'
jobs:
- job: build
- job: linux
timeoutInMinutes: 120
displayName: 'windows-msvc'
displayName: 'linux'
pool:
vmImage: ubuntu-latest
strategy:
maxParallel: 10
matrix:
linux:
BuildSuffix: 'linux'
ScriptFolder: 'linux'
steps:
- template: ./templates/sync-source.yml
parameters:
artifactSource: $(parameters.artifactSource)
needSubmodules: 'true'
- template: ./templates/build-single.yml
parameters:
artifactSource: 'false'
cache: $(parameters.cache)
version: $(DisplayVersion)
- job: msvc
timeoutInMinutes: 120
displayName: 'windows'
pool:
vmImage: windows-2022
steps:
+1 -1
View File
@@ -104,7 +104,7 @@ jobs:
run: |
glslangValidator --version
mkdir build
cmake . -B build -GNinja -DCMAKE_TOOLCHAIN_FILE="CMakeModules/MSVCCache.cmake" -DUSE_CCACHE=ON -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DCMAKE_BUILD_TYPE=Release -DGIT_BRANCH=pr-verify
cmake . -B build -GNinja -DCMAKE_TOOLCHAIN_FILE="CMakeModules/MSVCCache.cmake" -DUSE_CCACHE=ON -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DCMAKE_BUILD_TYPE=Release -DGIT_BRANCH=pr-verify -DYUZU_CRASH_DUMPS=ON
- name: Build
run: cmake --build build
- name: Cache Summary
+1 -1
View File
@@ -2,7 +2,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Build directory
[Bb]uild/
[Bb]uild*/
doc-build/
# Generated source files
+15 -3
View File
@@ -38,6 +38,8 @@ option(YUZU_USE_BUNDLED_OPUS "Compile bundled opus" ON)
option(YUZU_TESTS "Compile tests" ON)
CMAKE_DEPENDENT_OPTION(YUZU_CRASH_DUMPS "Compile Windows crash dump (Minidump) support" OFF "WIN32" OFF)
option(YUZU_USE_BUNDLED_VCPKG "Use vcpkg for yuzu dependencies" "${MSVC}")
option(YUZU_CHECK_SUBMODULES "Check if submodules are present" ON)
@@ -46,6 +48,9 @@ if (YUZU_USE_BUNDLED_VCPKG)
if (YUZU_TESTS)
list(APPEND VCPKG_MANIFEST_FEATURES "yuzu-tests")
endif()
if (YUZU_CRASH_DUMPS)
list(APPEND VCPKG_MANIFEST_FEATURES "dbghelp")
endif()
include(${CMAKE_SOURCE_DIR}/externals/vcpkg/scripts/buildsystems/vcpkg.cmake)
elseif(NOT "$ENV{VCPKG_TOOLCHAIN_FILE}" STREQUAL "")
@@ -247,7 +252,7 @@ if(ENABLE_QT)
endif()
# Check for headers
Include(FindPkgConfig REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(QT_DEP_GLU QUIET glu>=9.0.0)
if (NOT QT_DEP_GLU_FOUND)
message(FATAL_ERROR "Qt bundled pacakge dependency `glu` not found. \
@@ -381,7 +386,7 @@ endif()
# Ensure libusb is properly configured (based on dolphin libusb include)
if(NOT APPLE AND NOT YUZU_USE_BUNDLED_LIBUSB)
include(FindPkgConfig)
find_package(PkgConfig)
if (PKG_CONFIG_FOUND AND NOT CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD")
pkg_check_modules(LIBUSB QUIET libusb-1.0>=1.0.24)
else()
@@ -405,7 +410,7 @@ set(FFmpeg_COMPONENTS
swscale)
if (UNIX AND NOT APPLE)
Include(FindPkgConfig REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBVA libva)
endif()
if (NOT YUZU_USE_BUNDLED_FFMPEG)
@@ -447,6 +452,13 @@ elseif (WIN32)
# PSAPI is the Process Status API
set(PLATFORM_LIBRARIES ${PLATFORM_LIBRARIES} psapi imm32 version)
endif()
if (YUZU_CRASH_DUMPS)
find_library(DBGHELP_LIBRARY dbghelp)
if ("${DBGHELP_LIBRARY}" STREQUAL "DBGHELP_LIBRARY-NOTFOUND")
message(FATAL_ERROR "YUZU_CRASH_DUMPS enabled but dbghelp library not found")
endif()
endif()
elseif (CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU|SunOS)$")
set(PLATFORM_LIBRARIES rt)
endif()
+2 -8
View File
@@ -7,11 +7,6 @@ function(get_timestamp _var)
set(${_var} "${timestamp}" PARENT_SCOPE)
endfunction()
list(APPEND CMAKE_MODULE_PATH "${SRC_DIR}/externals/cmake-modules")
# Find the package here with the known path so that the GetGit commands can find it as well
find_package(Git QUIET PATHS "${GIT_EXECUTABLE}")
# generate git/build information
include(GetGitRevisionDescription)
if(NOT GIT_REF_SPEC)
@@ -29,6 +24,7 @@ get_timestamp(BUILD_DATE)
# Also if this is a CI build, add the build name (ie: Nightly, Canary) to the scm_rev file as well
set(REPO_NAME "")
set(BUILD_VERSION "0")
set(BUILD_ID ${DISPLAY_VERSION})
if (BUILD_REPOSITORY)
# regex capture the string nightly or canary into CMAKE_MATCH_1
string(REGEX MATCH "yuzu-emu/yuzu-?(.*)" OUTVAR ${BUILD_REPOSITORY})
@@ -57,6 +53,4 @@ if (BUILD_REPOSITORY)
endif()
endif()
# The variable SRC_DIR must be passed into the script
# (since it uses the current build directory for all values of CMAKE_*_DIR)
configure_file("${SRC_DIR}/src/common/scm_rev.cpp.in" "scm_rev.cpp" @ONLY)
configure_file(scm_rev.cpp.in scm_rev.cpp @ONLY)
+522 -456
View File
File diff suppressed because it is too large Load Diff
+522 -456
View File
File diff suppressed because it is too large Load Diff
+524 -458
View File
File diff suppressed because it is too large Load Diff
+588 -522
View File
File diff suppressed because it is too large Load Diff
+549 -478
View File
File diff suppressed because it is too large Load Diff
+547 -480
View File
File diff suppressed because it is too large Load Diff
+663 -577
View File
File diff suppressed because it is too large Load Diff
+522 -456
View File
File diff suppressed because it is too large Load Diff
+555 -489
View File
File diff suppressed because it is too large Load Diff
+548 -480
View File
File diff suppressed because it is too large Load Diff
+660 -589
View File
File diff suppressed because it is too large Load Diff
+522 -456
View File
File diff suppressed because it is too large Load Diff
+522 -456
View File
File diff suppressed because it is too large Load Diff
+522 -456
View File
File diff suppressed because it is too large Load Diff
+572 -504
View File
File diff suppressed because it is too large Load Diff
+572 -504
View File
File diff suppressed because it is too large Load Diff
+526 -458
View File
File diff suppressed because it is too large Load Diff
+522 -456
View File
File diff suppressed because it is too large Load Diff
+653 -581
View File
File diff suppressed because it is too large Load Diff
+522 -456
View File
File diff suppressed because it is too large Load Diff
+522 -456
View File
File diff suppressed because it is too large Load Diff
+531 -463
View File
File diff suppressed because it is too large Load Diff
+524 -456
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -43,7 +43,7 @@ if (NOT WIN32)
CACHE PATH "Paths to FFmpeg libraries" FORCE)
endforeach()
Include(FindPkgConfig REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBVA libva)
pkg_check_modules(CUDA cuda)
pkg_check_modules(FFNVCODEC ffnvcodec)
+1 -1
View File
@@ -108,7 +108,7 @@ if (MINGW OR (${CMAKE_SYSTEM_NAME} MATCHES "Linux") OR APPLE)
target_include_directories(usb INTERFACE "${LIBUSB_INCLUDE_DIRS}")
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
Include(FindPkgConfig)
find_package(PkgConfig)
pkg_check_modules(LIBUDEV REQUIRED libudev)
if (LIBUDEV_FOUND)
+1
View File
@@ -121,6 +121,7 @@ else()
if (ARCHITECTURE_x86_64)
add_compile_options("-mcx16")
add_compile_options("-fwrapv")
endif()
if (APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL Clang)
+1 -1
View File
@@ -8,7 +8,7 @@
namespace AudioCore {
AudioCore::AudioCore(Core::System& system) : audio_manager{std::make_unique<AudioManager>(system)} {
AudioCore::AudioCore(Core::System& system) : audio_manager{std::make_unique<AudioManager>()} {
CreateSinks();
// Must be created after the sinks
adsp = std::make_unique<AudioRenderer::ADSP::ADSP>(system, *output_sink);
+1 -1
View File
@@ -82,7 +82,7 @@ u32 Manager::GetDeviceNames(std::vector<AudioRenderer::AudioDevice::AudioDeviceN
auto input_devices{Sink::GetDeviceListForSink(Settings::values.sink_id.GetValue(), true)};
if (input_devices.size() > 1) {
names.push_back(AudioRenderer::AudioDevice::AudioDeviceName("Uac"));
names.emplace_back("Uac");
return 1;
}
return 0;
+9 -8
View File
@@ -1,14 +1,13 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "audio_core/audio_in_manager.h"
#include "audio_core/audio_manager.h"
#include "audio_core/audio_out_manager.h"
#include "core/core.h"
#include "core/hle/service/audio/errors.h"
namespace AudioCore {
AudioManager::AudioManager(Core::System& system_) : system{system_} {
AudioManager::AudioManager() {
thread = std::jthread([this]() { ThreadFunc(); });
}
@@ -27,7 +26,7 @@ Result AudioManager::SetOutManager(BufferEventFunc buffer_func) {
const auto index{events.GetManagerIndex(Event::Type::AudioOutManager)};
if (buffer_events[index] == nullptr) {
buffer_events[index] = buffer_func;
buffer_events[index] = std::move(buffer_func);
needs_update = true;
events.SetAudioEvent(Event::Type::AudioOutManager, true);
}
@@ -43,7 +42,7 @@ Result AudioManager::SetInManager(BufferEventFunc buffer_func) {
const auto index{events.GetManagerIndex(Event::Type::AudioInManager)};
if (buffer_events[index] == nullptr) {
buffer_events[index] = buffer_func;
buffer_events[index] = std::move(buffer_func);
needs_update = true;
events.SetAudioEvent(Event::Type::AudioInManager, true);
}
@@ -60,19 +59,21 @@ void AudioManager::ThreadFunc() {
running = true;
while (running) {
auto timed_out{events.Wait(l, std::chrono::seconds(2))};
const auto timed_out{events.Wait(l, std::chrono::seconds(2))};
if (events.CheckAudioEventSet(Event::Type::Max)) {
break;
}
for (size_t i = 0; i < buffer_events.size(); i++) {
if (events.CheckAudioEventSet(Event::Type(i)) || timed_out) {
const auto event_type = static_cast<Event::Type>(i);
if (events.CheckAudioEventSet(event_type) || timed_out) {
if (buffer_events[i]) {
buffer_events[i]();
}
}
events.SetAudioEvent(Event::Type(i), false);
events.SetAudioEvent(event_type, false);
}
}
}
+2 -17
View File
@@ -10,22 +10,11 @@
#include <thread>
#include "audio_core/audio_event.h"
#include "core/hle/service/audio/errors.h"
namespace Core {
class System;
}
union Result;
namespace AudioCore {
namespace AudioOut {
class Manager;
}
namespace AudioIn {
class Manager;
}
/**
* The AudioManager's main purpose is to wait for buffer events for the audio in and out managers,
* and call an associated callback to release buffers.
@@ -43,7 +32,7 @@ class AudioManager {
using BufferEventFunc = std::function<void()>;
public:
explicit AudioManager(Core::System& system);
explicit AudioManager();
/**
* Shutdown the audio manager.
@@ -80,10 +69,6 @@ private:
*/
void ThreadFunc();
/// Core system
Core::System& system;
/// Have sessions started palying?
bool sessions_started{};
/// Is the main thread running?
std::atomic<bool> running{};
/// Unused
+1 -1
View File
@@ -74,7 +74,7 @@ void Manager::BufferReleaseAndRegister() {
u32 Manager::GetAudioOutDeviceNames(
std::vector<AudioRenderer::AudioDevice::AudioDeviceName>& names) const {
names.push_back({"DeviceOut"});
names.emplace_back("DeviceOut");
return 1;
}
+3 -3
View File
@@ -25,8 +25,8 @@ SystemManager& Manager::GetSystemManager() {
return *system_manager;
}
auto Manager::GetWorkBufferSize(const AudioRendererParameterInternal& params, u64& out_count)
-> Result {
Result Manager::GetWorkBufferSize(const AudioRendererParameterInternal& params,
u64& out_count) const {
if (!CheckValidRevision(params.revision)) {
return Service::Audio::ERR_INVALID_REVISION;
}
@@ -54,7 +54,7 @@ void Manager::ReleaseSessionId(const s32 session_id) {
session_ids[--session_count] = session_id;
}
u32 Manager::GetSessionCount() {
u32 Manager::GetSessionCount() const {
std::scoped_lock l{session_lock};
return session_count;
}
+3 -3
View File
@@ -46,7 +46,7 @@ public:
* @param out_count - Output size of the required workbuffer.
* @return Result code.
*/
Result GetWorkBufferSize(const AudioRendererParameterInternal& params, u64& out_count);
Result GetWorkBufferSize(const AudioRendererParameterInternal& params, u64& out_count) const;
/**
* Get a new session id.
@@ -60,7 +60,7 @@ public:
*
* @return The number of active sessions.
*/
u32 GetSessionCount();
u32 GetSessionCount() const;
/**
* Add a renderer system to the manager.
@@ -94,7 +94,7 @@ private:
/// Number of active renderers
u32 session_count{};
/// Lock for interacting with the sessions
std::mutex session_lock{};
mutable std::mutex session_lock{};
/// Regularly generates commands from the registered systems for the AudioRenderer
std::unique_ptr<SystemManager> system_manager{};
};
+2 -2
View File
@@ -36,7 +36,7 @@ public:
*
* @param buffer - The new buffer.
*/
void AppendBuffer(AudioBuffer& buffer) {
void AppendBuffer(const AudioBuffer& buffer) {
std::scoped_lock l{lock};
buffers[appended_index] = buffer;
appended_count++;
@@ -93,7 +93,7 @@ public:
*
* @return Is the buffer was released.
*/
bool ReleaseBuffers(Core::Timing::CoreTiming& core_timing, DeviceSession& session) {
bool ReleaseBuffers(const Core::Timing::CoreTiming& core_timing, const DeviceSession& session) {
std::scoped_lock l{lock};
bool buffer_released{false};
while (registered_count > 0) {
+8 -8
View File
@@ -73,12 +73,12 @@ void DeviceSession::Stop() {
}
}
void DeviceSession::AppendBuffers(std::span<AudioBuffer> buffers) const {
for (size_t i = 0; i < buffers.size(); i++) {
void DeviceSession::AppendBuffers(std::span<const AudioBuffer> buffers) const {
for (const auto& buffer : buffers) {
Sink::SinkBuffer new_buffer{
.frames = buffers[i].size / (channel_count * sizeof(s16)),
.frames = buffer.size / (channel_count * sizeof(s16)),
.frames_played = 0,
.tag = buffers[i].tag,
.tag = buffer.tag,
.consumed = false,
};
@@ -86,21 +86,21 @@ void DeviceSession::AppendBuffers(std::span<AudioBuffer> buffers) const {
std::vector<s16> samples{};
stream->AppendBuffer(new_buffer, samples);
} else {
std::vector<s16> samples(buffers[i].size / sizeof(s16));
system.Memory().ReadBlockUnsafe(buffers[i].samples, samples.data(), buffers[i].size);
std::vector<s16> samples(buffer.size / sizeof(s16));
system.Memory().ReadBlockUnsafe(buffer.samples, samples.data(), buffer.size);
stream->AppendBuffer(new_buffer, samples);
}
}
}
void DeviceSession::ReleaseBuffer(AudioBuffer& buffer) const {
void DeviceSession::ReleaseBuffer(const AudioBuffer& buffer) const {
if (type == Sink::StreamType::In) {
auto samples{stream->ReleaseBuffer(buffer.size / sizeof(s16))};
system.Memory().WriteBlockUnsafe(buffer.samples, samples.data(), buffer.size);
}
}
bool DeviceSession::IsBufferConsumed(AudioBuffer& buffer) const {
bool DeviceSession::IsBufferConsumed(const AudioBuffer& buffer) const {
return played_sample_count >= buffer.end_timestamp;
}
+3 -3
View File
@@ -62,14 +62,14 @@ public:
*
* @param buffers - The buffers to play.
*/
void AppendBuffers(std::span<AudioBuffer> buffers) const;
void AppendBuffers(std::span<const AudioBuffer> buffers) const;
/**
* (Audio In only) Pop samples from the backend, and write them back to this buffer's address.
*
* @param buffer - The buffer to write to.
*/
void ReleaseBuffer(AudioBuffer& buffer) const;
void ReleaseBuffer(const AudioBuffer& buffer) const;
/**
* Check if the buffer for the given tag has been consumed by the backend.
@@ -78,7 +78,7 @@ public:
*
* @return true if the buffer has been consumed, otherwise false.
*/
bool IsBufferConsumed(AudioBuffer& buffer) const;
bool IsBufferConsumed(const AudioBuffer& buffer) const;
/**
* Start this device session, starting the backend stream.
+4 -4
View File
@@ -72,7 +72,7 @@ Kernel::KReadableEvent& In::GetBufferEvent() {
return event->GetReadableEvent();
}
f32 In::GetVolume() {
f32 In::GetVolume() const {
std::scoped_lock l{parent_mutex};
return system.GetVolume();
}
@@ -82,17 +82,17 @@ void In::SetVolume(f32 volume) {
system.SetVolume(volume);
}
bool In::ContainsAudioBuffer(u64 tag) {
bool In::ContainsAudioBuffer(u64 tag) const {
std::scoped_lock l{parent_mutex};
return system.ContainsAudioBuffer(tag);
}
u32 In::GetBufferCount() {
u32 In::GetBufferCount() const {
std::scoped_lock l{parent_mutex};
return system.GetBufferCount();
}
u64 In::GetPlayedSampleCount() {
u64 In::GetPlayedSampleCount() const {
std::scoped_lock l{parent_mutex};
return system.GetPlayedSampleCount();
}
+4 -4
View File
@@ -102,7 +102,7 @@ public:
*
* @return The current volume.
*/
f32 GetVolume();
f32 GetVolume() const;
/**
* Set the system volume.
@@ -117,21 +117,21 @@ public:
* @param tag - The tag to search for.
* @return True if the buffer is in the system, otherwise false.
*/
bool ContainsAudioBuffer(u64 tag);
bool ContainsAudioBuffer(u64 tag) const;
/**
* Get the maximum number of buffers.
*
* @return The maximum number of buffers.
*/
u32 GetBufferCount();
u32 GetBufferCount() const;
/**
* Get the total played sample count for this audio in.
*
* @return The played sample count.
*/
u64 GetPlayedSampleCount();
u64 GetPlayedSampleCount() const;
private:
/// The AudioIn::Manager this audio in is registered with
+13 -11
View File
@@ -34,16 +34,16 @@ size_t System::GetSessionId() const {
return session_id;
}
std::string_view System::GetDefaultDeviceName() {
std::string_view System::GetDefaultDeviceName() const {
return "BuiltInHeadset";
}
std::string_view System::GetDefaultUacDeviceName() {
std::string_view System::GetDefaultUacDeviceName() const {
return "Uac";
}
Result System::IsConfigValid(const std::string_view device_name,
const AudioInParameter& in_params) {
const AudioInParameter& in_params) const {
if ((device_name.size() > 0) &&
(device_name != GetDefaultDeviceName() && device_name != GetDefaultUacDeviceName())) {
return Service::Audio::ERR_INVALID_DEVICE_NAME;
@@ -114,12 +114,14 @@ bool System::AppendBuffer(const AudioInBuffer& buffer, const u64 tag) {
}
const auto timestamp{buffers.GetNextTimestamp()};
AudioBuffer new_buffer{.start_timestamp = timestamp,
.end_timestamp = timestamp + buffer.size / (channel_count * sizeof(s16)),
.played_timestamp = 0,
.samples = buffer.samples,
.tag = tag,
.size = buffer.size};
const AudioBuffer new_buffer{
.start_timestamp = timestamp,
.end_timestamp = timestamp + buffer.size / (channel_count * sizeof(s16)),
.played_timestamp = 0,
.samples = buffer.samples,
.tag = tag,
.size = buffer.size,
};
buffers.AppendBuffer(new_buffer);
RegisterBuffers();
@@ -200,11 +202,11 @@ void System::SetVolume(const f32 volume_) {
session->SetVolume(volume_);
}
bool System::ContainsAudioBuffer(const u64 tag) {
bool System::ContainsAudioBuffer(const u64 tag) const {
return buffers.ContainsBuffer(tag);
}
u32 System::GetBufferCount() {
u32 System::GetBufferCount() const {
return buffers.GetAppendedRegisteredCount();
}
+5 -5
View File
@@ -68,7 +68,7 @@ public:
*
* @return The default audio input device name.
*/
std::string_view GetDefaultDeviceName();
std::string_view GetDefaultDeviceName() const;
/**
* Get the default USB audio input device name.
@@ -77,7 +77,7 @@ public:
*
* @return The default USB audio input device name.
*/
std::string_view GetDefaultUacDeviceName();
std::string_view GetDefaultUacDeviceName() const;
/**
* Is the given initialize config valid?
@@ -86,7 +86,7 @@ public:
* @param in_params - Input parameters, see AudioInParameter.
* @return Result code.
*/
Result IsConfigValid(std::string_view device_name, const AudioInParameter& in_params);
Result IsConfigValid(std::string_view device_name, const AudioInParameter& in_params) const;
/**
* Initialize this system.
@@ -218,14 +218,14 @@ public:
* @param tag - Unique tag to search for.
* @return True if the buffer is in the system, otherwise false.
*/
bool ContainsAudioBuffer(u64 tag);
bool ContainsAudioBuffer(u64 tag) const;
/**
* Get the maximum number of usable buffers (default 32).
*
* @return The number of buffers.
*/
u32 GetBufferCount();
u32 GetBufferCount() const;
/**
* Get the total number of samples played by this system.
+4 -4
View File
@@ -72,7 +72,7 @@ Kernel::KReadableEvent& Out::GetBufferEvent() {
return event->GetReadableEvent();
}
f32 Out::GetVolume() {
f32 Out::GetVolume() const {
std::scoped_lock l{parent_mutex};
return system.GetVolume();
}
@@ -82,17 +82,17 @@ void Out::SetVolume(const f32 volume) {
system.SetVolume(volume);
}
bool Out::ContainsAudioBuffer(const u64 tag) {
bool Out::ContainsAudioBuffer(const u64 tag) const {
std::scoped_lock l{parent_mutex};
return system.ContainsAudioBuffer(tag);
}
u32 Out::GetBufferCount() {
u32 Out::GetBufferCount() const {
std::scoped_lock l{parent_mutex};
return system.GetBufferCount();
}
u64 Out::GetPlayedSampleCount() {
u64 Out::GetPlayedSampleCount() const {
std::scoped_lock l{parent_mutex};
return system.GetPlayedSampleCount();
}
+4 -4
View File
@@ -102,7 +102,7 @@ public:
*
* @return The current volume.
*/
f32 GetVolume();
f32 GetVolume() const;
/**
* Set the system volume.
@@ -117,21 +117,21 @@ public:
* @param tag - The tag to search for.
* @return True if the buffer is in the system, otherwise false.
*/
bool ContainsAudioBuffer(u64 tag);
bool ContainsAudioBuffer(u64 tag) const;
/**
* Get the maximum number of buffers.
*
* @return The maximum number of buffers.
*/
u32 GetBufferCount();
u32 GetBufferCount() const;
/**
* Get the total played sample count for this audio out.
*
* @return The played sample count.
*/
u64 GetPlayedSampleCount();
u64 GetPlayedSampleCount() const;
private:
/// The AudioOut::Manager this audio out is registered with
+13 -10
View File
@@ -27,11 +27,12 @@ void System::Finalize() {
buffer_event->GetWritableEvent().Signal();
}
std::string_view System::GetDefaultOutputDeviceName() {
std::string_view System::GetDefaultOutputDeviceName() const {
return "DeviceOut";
}
Result System::IsConfigValid(std::string_view device_name, const AudioOutParameter& in_params) {
Result System::IsConfigValid(std::string_view device_name,
const AudioOutParameter& in_params) const {
if ((device_name.size() > 0) && (device_name != GetDefaultOutputDeviceName())) {
return Service::Audio::ERR_INVALID_DEVICE_NAME;
}
@@ -113,12 +114,14 @@ bool System::AppendBuffer(const AudioOutBuffer& buffer, u64 tag) {
}
const auto timestamp{buffers.GetNextTimestamp()};
AudioBuffer new_buffer{.start_timestamp = timestamp,
.end_timestamp = timestamp + buffer.size / (channel_count * sizeof(s16)),
.played_timestamp = 0,
.samples = buffer.samples,
.tag = tag,
.size = buffer.size};
const AudioBuffer new_buffer{
.start_timestamp = timestamp,
.end_timestamp = timestamp + buffer.size / (channel_count * sizeof(s16)),
.played_timestamp = 0,
.samples = buffer.samples,
.tag = tag,
.size = buffer.size,
};
buffers.AppendBuffer(new_buffer);
RegisterBuffers();
@@ -198,11 +201,11 @@ void System::SetVolume(const f32 volume_) {
session->SetVolume(volume_);
}
bool System::ContainsAudioBuffer(const u64 tag) {
bool System::ContainsAudioBuffer(const u64 tag) const {
return buffers.ContainsBuffer(tag);
}
u32 System::GetBufferCount() {
u32 System::GetBufferCount() const {
return buffers.GetAppendedRegisteredCount();
}
+4 -4
View File
@@ -68,7 +68,7 @@ public:
*
* @return The default audio output device name.
*/
std::string_view GetDefaultOutputDeviceName();
std::string_view GetDefaultOutputDeviceName() const;
/**
* Is the given initialize config valid?
@@ -77,7 +77,7 @@ public:
* @param in_params - Input parameters, see AudioOutParameter.
* @return Result code.
*/
Result IsConfigValid(std::string_view device_name, const AudioOutParameter& in_params);
Result IsConfigValid(std::string_view device_name, const AudioOutParameter& in_params) const;
/**
* Initialize this system.
@@ -209,14 +209,14 @@ public:
* @param tag - Unique tag to search for.
* @return True if the buffer is in the system, otherwise false.
*/
bool ContainsAudioBuffer(u64 tag);
bool ContainsAudioBuffer(u64 tag) const;
/**
* Get the maximum number of usable buffers (default 32).
*
* @return The number of buffers.
*/
u32 GetBufferCount();
u32 GetBufferCount() const;
/**
* Get the total number of samples played by this system.
+1 -1
View File
@@ -50,7 +50,7 @@ u32 ADSP::GetRemainCommandCount(const u32 session_id) const {
return render_mailbox.GetRemainCommandCount(session_id);
}
void ADSP::SendCommandBuffer(const u32 session_id, CommandBuffer& command_buffer) {
void ADSP::SendCommandBuffer(const u32 session_id, const CommandBuffer& command_buffer) {
render_mailbox.SetCommandBuffer(session_id, command_buffer);
}
+1 -1
View File
@@ -131,7 +131,7 @@ public:
* @param session_id - The session id to check (0 or 1).
* @param command_buffer - The command buffer to process.
*/
void SendCommandBuffer(u32 session_id, CommandBuffer& command_buffer);
void SendCommandBuffer(u32 session_id, const CommandBuffer& command_buffer);
/**
* Clear the command buffers (does not clear the time taken or the remaining command count)
@@ -47,11 +47,11 @@ RenderMessage AudioRenderer_Mailbox::ADSPWaitMessage() {
return msg;
}
CommandBuffer& AudioRenderer_Mailbox::GetCommandBuffer(const s32 session_id) {
CommandBuffer& AudioRenderer_Mailbox::GetCommandBuffer(const u32 session_id) {
return command_buffers[session_id];
}
void AudioRenderer_Mailbox::SetCommandBuffer(const u32 session_id, CommandBuffer& buffer) {
void AudioRenderer_Mailbox::SetCommandBuffer(const u32 session_id, const CommandBuffer& buffer) {
command_buffers[session_id] = buffer;
}
@@ -132,7 +132,7 @@ void AudioRenderer::CreateSinkStreams() {
}
void AudioRenderer::ThreadFunc() {
constexpr char name[]{"yuzu:AudioRenderer"};
constexpr char name[]{"AudioRenderer"};
MicroProfileOnThreadCreate(name);
Common::SetCurrentThreadName(name);
Common::SetCurrentThreadPriority(Common::ThreadPriority::Critical);
@@ -83,7 +83,7 @@ public:
* @param session_id - The session id to get (0 or 1).
* @return The command buffer.
*/
CommandBuffer& GetCommandBuffer(s32 session_id);
CommandBuffer& GetCommandBuffer(u32 session_id);
/**
* Set the command buffer with the given session id (0 or 1).
@@ -91,7 +91,7 @@ public:
* @param session_id - The session id to get (0 or 1).
* @param buffer - The command buffer to set.
*/
void SetCommandBuffer(u32 session_id, CommandBuffer& buffer);
void SetCommandBuffer(u32 session_id, const CommandBuffer& buffer);
/**
* Get the total render time taken for the last command lists sent.
+28 -6
View File
@@ -1,6 +1,9 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <array>
#include <span>
#include "audio_core/audio_core.h"
#include "audio_core/common/feature_support.h"
#include "audio_core/renderer/audio_device.h"
@@ -9,14 +12,33 @@
namespace AudioCore::AudioRenderer {
constexpr std::array usb_device_names{
AudioDevice::AudioDeviceName{"AudioStereoJackOutput"},
AudioDevice::AudioDeviceName{"AudioBuiltInSpeakerOutput"},
AudioDevice::AudioDeviceName{"AudioTvOutput"},
AudioDevice::AudioDeviceName{"AudioUsbDeviceOutput"},
};
constexpr std::array device_names{
AudioDevice::AudioDeviceName{"AudioStereoJackOutput"},
AudioDevice::AudioDeviceName{"AudioBuiltInSpeakerOutput"},
AudioDevice::AudioDeviceName{"AudioTvOutput"},
};
constexpr std::array output_device_names{
AudioDevice::AudioDeviceName{"AudioBuiltInSpeakerOutput"},
AudioDevice::AudioDeviceName{"AudioTvOutput"},
AudioDevice::AudioDeviceName{"AudioExternalOutput"},
};
AudioDevice::AudioDevice(Core::System& system, const u64 applet_resource_user_id_,
const u32 revision)
: output_sink{system.AudioCore().GetOutputSink()},
applet_resource_user_id{applet_resource_user_id_}, user_revision{revision} {}
u32 AudioDevice::ListAudioDeviceName(std::vector<AudioDeviceName>& out_buffer,
const size_t max_count) {
std::span<AudioDeviceName> names{};
const size_t max_count) const {
std::span<const AudioDeviceName> names{};
if (CheckFeatureSupported(SupportTags::AudioUsbDeviceOutput, user_revision)) {
names = usb_device_names;
@@ -24,7 +46,7 @@ u32 AudioDevice::ListAudioDeviceName(std::vector<AudioDeviceName>& out_buffer,
names = device_names;
}
u32 out_count{static_cast<u32>(std::min(max_count, names.size()))};
const u32 out_count{static_cast<u32>(std::min(max_count, names.size()))};
for (u32 i = 0; i < out_count; i++) {
out_buffer.push_back(names[i]);
}
@@ -32,8 +54,8 @@ u32 AudioDevice::ListAudioDeviceName(std::vector<AudioDeviceName>& out_buffer,
}
u32 AudioDevice::ListAudioOutputDeviceName(std::vector<AudioDeviceName>& out_buffer,
const size_t max_count) {
u32 out_count{static_cast<u32>(std::min(max_count, output_device_names.size()))};
const size_t max_count) const {
const u32 out_count{static_cast<u32>(std::min(max_count, output_device_names.size()))};
for (u32 i = 0; i < out_count; i++) {
out_buffer.push_back(output_device_names[i]);
@@ -45,7 +67,7 @@ void AudioDevice::SetDeviceVolumes(const f32 volume) {
output_sink.SetDeviceVolume(volume);
}
f32 AudioDevice::GetDeviceVolume([[maybe_unused]] std::string_view name) {
f32 AudioDevice::GetDeviceVolume([[maybe_unused]] std::string_view name) const {
return output_sink.GetDeviceVolume();
}
+7 -15
View File
@@ -3,7 +3,7 @@
#pragma once
#include <span>
#include <string_view>
#include "audio_core/audio_render_manager.h"
@@ -23,21 +23,13 @@ namespace AudioRenderer {
class AudioDevice {
public:
struct AudioDeviceName {
std::array<char, 0x100> name;
std::array<char, 0x100> name{};
AudioDeviceName(const char* name_) {
std::strncpy(name.data(), name_, name.size());
constexpr AudioDeviceName(std::string_view name_) {
name_.copy(name.data(), name.size() - 1);
}
};
std::array<AudioDeviceName, 4> usb_device_names{"AudioStereoJackOutput",
"AudioBuiltInSpeakerOutput", "AudioTvOutput",
"AudioUsbDeviceOutput"};
std::array<AudioDeviceName, 3> device_names{"AudioStereoJackOutput",
"AudioBuiltInSpeakerOutput", "AudioTvOutput"};
std::array<AudioDeviceName, 3> output_device_names{"AudioBuiltInSpeakerOutput", "AudioTvOutput",
"AudioExternalOutput"};
explicit AudioDevice(Core::System& system, u64 applet_resource_user_id, u32 revision);
/**
@@ -47,7 +39,7 @@ public:
* @param max_count - Maximum number of devices to write (count of out_buffer).
* @return Number of device names written.
*/
u32 ListAudioDeviceName(std::vector<AudioDeviceName>& out_buffer, size_t max_count);
u32 ListAudioDeviceName(std::vector<AudioDeviceName>& out_buffer, size_t max_count) const;
/**
* Get a list of the available output devices.
@@ -57,7 +49,7 @@ public:
* @param max_count - Maximum number of devices to write (count of out_buffer).
* @return Number of device names written.
*/
u32 ListAudioOutputDeviceName(std::vector<AudioDeviceName>& out_buffer, size_t max_count);
u32 ListAudioOutputDeviceName(std::vector<AudioDeviceName>& out_buffer, size_t max_count) const;
/**
* Set the volume of all streams in the backend sink.
@@ -73,7 +65,7 @@ public:
* @param name - Name of the device to check. Unused.
* @return Volume of the device.
*/
f32 GetDeviceVolume(std::string_view name);
f32 GetDeviceVolume(std::string_view name) const;
private:
/// Backend output sink for the device
@@ -34,7 +34,7 @@ void BehaviorInfo::ClearError() {
error_count = 0;
}
void BehaviorInfo::AppendError(ErrorInfo& error) {
void BehaviorInfo::AppendError(const ErrorInfo& error) {
LOG_ERROR(Service_Audio, "Error during RequestUpdate, reporting code {:04X} address {:08X}",
error.error_code.raw, error.address);
if (error_count < MaxErrors) {
@@ -42,7 +42,7 @@ void BehaviorInfo::AppendError(ErrorInfo& error) {
}
}
void BehaviorInfo::CopyErrorInfo(std::span<ErrorInfo> out_errors, u32& out_count) {
void BehaviorInfo::CopyErrorInfo(std::span<ErrorInfo> out_errors, u32& out_count) const {
out_count = std::min(error_count, MaxErrors);
for (size_t i = 0; i < MaxErrors; i++) {
@@ -94,7 +94,7 @@ public:
*
* @param error - The new error.
*/
void AppendError(ErrorInfo& error);
void AppendError(const ErrorInfo& error);
/**
* Copy errors to the given output container.
@@ -102,7 +102,7 @@ public:
* @param out_errors - Output container to receive the errors.
* @param out_count - The number of errors written.
*/
void CopyErrorInfo(std::span<ErrorInfo> out_errors, u32& out_count);
void CopyErrorInfo(std::span<ErrorInfo> out_errors, u32& out_count) const;
/**
* Update the behaviour flags.
@@ -485,7 +485,7 @@ Result InfoUpdater::UpdateBehaviorInfo(BehaviorInfo& behaviour_) {
return ResultSuccess;
}
Result InfoUpdater::UpdateErrorInfo(BehaviorInfo& behaviour_) {
Result InfoUpdater::UpdateErrorInfo(const BehaviorInfo& behaviour_) {
auto out_params{reinterpret_cast<BehaviorInfo::OutStatus*>(output)};
behaviour_.CopyErrorInfo(out_params->errors, out_params->error_count);
@@ -130,7 +130,7 @@ public:
* @param behaviour - Behaviour to update.
* @return Result code.
*/
Result UpdateErrorInfo(BehaviorInfo& behaviour);
Result UpdateErrorInfo(const BehaviorInfo& behaviour);
/**
* Update splitter.
+2 -2
View File
@@ -99,7 +99,7 @@ public:
return out_sample;
}
Common::FixedPoint<50, 14> Read() {
Common::FixedPoint<50, 14> Read() const {
return *output;
}
@@ -110,7 +110,7 @@ public:
}
}
Common::FixedPoint<50, 14> TapOut(const s32 index) {
Common::FixedPoint<50, 14> TapOut(const s32 index) const {
auto out{input - (index + 1)};
if (out < buffer.data()) {
out += max_delay + 1;
+2 -2
View File
@@ -95,7 +95,7 @@ public:
return out_sample;
}
Common::FixedPoint<50, 14> Read() {
Common::FixedPoint<50, 14> Read() const {
return *output;
}
@@ -106,7 +106,7 @@ public:
}
}
Common::FixedPoint<50, 14> TapOut(const s32 index) {
Common::FixedPoint<50, 14> TapOut(const s32 index) const {
auto out{input - (index + 1)};
if (out < buffer.data()) {
out += sample_count;
+2 -2
View File
@@ -56,7 +56,7 @@ class NodeStates {
*
* @return The current stack position.
*/
u32 Count() {
u32 Count() const {
return pos;
}
@@ -83,7 +83,7 @@ class NodeStates {
*
* @return The node on the top of the stack.
*/
u32 top() {
u32 top() const {
return stack[pos - 1];
}
+1 -1
View File
@@ -94,7 +94,7 @@ bool SystemManager::Remove(System& system_) {
}
void SystemManager::ThreadFunc() {
constexpr char name[]{"yuzu:AudioRenderSystemManager"};
constexpr char name[]{"AudioRenderSystemManager"};
MicroProfileOnThreadCreate(name);
Common::SetCurrentThreadName(name);
Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
+29 -2
View File
@@ -66,10 +66,10 @@ public:
const auto latency_error = cubeb_get_min_latency(ctx, &params, &minimum_latency);
if (latency_error != CUBEB_OK) {
LOG_CRITICAL(Audio_Sink, "Error getting minimum latency, error: {}", latency_error);
minimum_latency = 256U;
minimum_latency = TargetSampleCount * 2;
}
minimum_latency = std::max(minimum_latency, 256u);
minimum_latency = std::max(minimum_latency, TargetSampleCount * 2);
LOG_INFO(Service_Audio,
"Opening cubeb stream {} type {} with: rate {} channels {} (system channels {}) "
@@ -326,4 +326,31 @@ std::vector<std::string> ListCubebSinkDevices(bool capture) {
return device_list;
}
u32 GetCubebLatency() {
cubeb* ctx;
if (cubeb_init(&ctx, "yuzu Latency Getter", nullptr) != CUBEB_OK) {
LOG_CRITICAL(Audio_Sink, "cubeb_init failed");
// Return a large latency so we choose SDL instead.
return 10000u;
}
cubeb_stream_params params{};
params.rate = TargetSampleRate;
params.channels = 2;
params.format = CUBEB_SAMPLE_S16LE;
params.prefs = CUBEB_STREAM_PREF_NONE;
params.layout = CUBEB_LAYOUT_STEREO;
u32 latency{0};
const auto latency_error = cubeb_get_min_latency(ctx, &params, &latency);
if (latency_error != CUBEB_OK) {
LOG_CRITICAL(Audio_Sink, "Error getting minimum latency, error: {}", latency_error);
latency = TargetSampleCount * 2;
}
latency = std::max(latency, TargetSampleCount * 2);
cubeb_destroy(ctx);
return latency;
}
} // namespace AudioCore::Sink
+7
View File
@@ -96,4 +96,11 @@ private:
*/
std::vector<std::string> ListCubebSinkDevices(bool capture);
/**
* Get the reported latency for this sink.
*
* @return Minimum latency for this sink.
*/
u32 GetCubebLatency();
} // namespace AudioCore::Sink
+5 -5
View File
@@ -47,11 +47,7 @@ public:
spec.freq = TargetSampleRate;
spec.channels = static_cast<u8>(device_channels);
spec.format = AUDIO_S16SYS;
if (type == StreamType::Render) {
spec.samples = TargetSampleCount;
} else {
spec.samples = 1024;
}
spec.samples = TargetSampleCount * 2;
spec.callback = &SDLSinkStream::DataCallback;
spec.userdata = this;
@@ -240,4 +236,8 @@ std::vector<std::string> ListSDLSinkDevices(bool capture) {
return device_list;
}
u32 GetSDLLatency() {
return TargetSampleCount * 2;
}
} // namespace AudioCore::Sink
+7
View File
@@ -87,4 +87,11 @@ private:
*/
std::vector<std::string> ListSDLSinkDevices(bool capture);
/**
* Get the reported latency for this sink.
*
* @return Minimum latency for this sink.
*/
u32 GetSDLLatency();
} // namespace AudioCore::Sink
+44 -22
View File
@@ -21,58 +21,80 @@ namespace {
struct SinkDetails {
using FactoryFn = std::unique_ptr<Sink> (*)(std::string_view);
using ListDevicesFn = std::vector<std::string> (*)(bool);
using LatencyFn = u32 (*)();
/// Name for this sink.
const char* id;
std::string_view id;
/// A method to call to construct an instance of this type of sink.
FactoryFn factory;
/// A method to call to list available devices.
ListDevicesFn list_devices;
/// Method to get the latency of this backend.
LatencyFn latency;
};
// sink_details is ordered in terms of desirability, with the best choice at the top.
constexpr SinkDetails sink_details[] = {
#ifdef HAVE_CUBEB
SinkDetails{"cubeb",
[](std::string_view device_id) -> std::unique_ptr<Sink> {
return std::make_unique<CubebSink>(device_id);
},
&ListCubebSinkDevices},
SinkDetails{
"cubeb",
[](std::string_view device_id) -> std::unique_ptr<Sink> {
return std::make_unique<CubebSink>(device_id);
},
&ListCubebSinkDevices,
&GetCubebLatency,
},
#endif
#ifdef HAVE_SDL2
SinkDetails{"sdl2",
[](std::string_view device_id) -> std::unique_ptr<Sink> {
return std::make_unique<SDLSink>(device_id);
},
&ListSDLSinkDevices},
SinkDetails{
"sdl",
[](std::string_view device_id) -> std::unique_ptr<Sink> {
return std::make_unique<SDLSink>(device_id);
},
&ListSDLSinkDevices,
&GetSDLLatency,
},
#endif
SinkDetails{"null",
[](std::string_view device_id) -> std::unique_ptr<Sink> {
return std::make_unique<NullSink>(device_id);
},
[](bool capture) { return std::vector<std::string>{"null"}; }},
[](bool capture) { return std::vector<std::string>{"null"}; }, []() { return 0u; }},
};
const SinkDetails& GetOutputSinkDetails(std::string_view sink_id) {
auto iter =
std::find_if(std::begin(sink_details), std::end(sink_details),
[sink_id](const auto& sink_detail) { return sink_detail.id == sink_id; });
const auto find_backend{[](std::string_view id) {
return std::find_if(std::begin(sink_details), std::end(sink_details),
[&id](const auto& sink_detail) { return sink_detail.id == id; });
}};
if (sink_id == "auto" || iter == std::end(sink_details)) {
if (sink_id != "auto") {
LOG_ERROR(Audio, "Invalid sink_id {}", sink_id);
auto iter = find_backend(sink_id);
if (sink_id == "auto") {
// Auto-select a backend. Prefer CubeB, but it may report a large minimum latency which
// causes audio issues, in that case go with SDL.
#if defined(HAVE_CUBEB) && defined(HAVE_SDL2)
iter = find_backend("cubeb");
if (iter->latency() > TargetSampleCount * 3) {
iter = find_backend("sdl");
}
// Auto-select.
// sink_details is ordered in terms of desirability, with the best choice at the front.
#else
iter = std::begin(sink_details);
#endif
LOG_INFO(Service_Audio, "Auto-selecting the {} backend", iter->id);
}
if (iter == std::end(sink_details)) {
LOG_ERROR(Audio, "Invalid sink_id {}", sink_id);
iter = find_backend("null");
}
return *iter;
}
} // Anonymous namespace
std::vector<const char*> GetSinkIDs() {
std::vector<const char*> sink_ids(std::size(sink_details));
std::vector<std::string_view> GetSinkIDs() {
std::vector<std::string_view> sink_ids(std::size(sink_details));
std::transform(std::begin(sink_details), std::end(sink_details), std::begin(sink_ids),
[](const auto& sink) { return sink.id; });
+1 -1
View File
@@ -19,7 +19,7 @@ class Sink;
*
* @return Vector of available sink names.
*/
std::vector<const char*> GetSinkIDs();
std::vector<std::string_view> GetSinkIDs();
/**
* Gets the list of devices for a particular sink identified by the given ID.
+7 -2
View File
@@ -214,8 +214,13 @@ void SinkStream::ProcessAudioOutAndRender(std::span<s16> output_buffer, std::siz
// video play out without attempting to stall.
// Can hopefully remove this later with a more complete NVDEC implementation.
const auto nvdec_active{system.AudioCore().IsNVDECActive()};
if (!nvdec_active && queued_buffers > max_queue_size) {
// Core timing cannot be paused in single-core mode, so Stall ends up being called over and over
// and never recovers to a normal state, so just skip attempting to sync things on single-core.
if (system.IsMulticore() && !nvdec_active && queued_buffers > max_queue_size) {
Stall();
} else if (system.IsMulticore() && queued_buffers <= max_queue_size) {
Unstall();
}
while (frames_written < num_frames) {
@@ -255,7 +260,7 @@ void SinkStream::ProcessAudioOutAndRender(std::span<s16> output_buffer, std::siz
std::memcpy(&last_frame[0], &output_buffer[(frames_written - 1) * frame_size],
frame_size_bytes);
if (stalled && queued_buffers <= max_queue_size) {
if (system.IsMulticore() && queued_buffers <= max_queue_size) {
Unstall();
}
}
+1 -1
View File
@@ -151,7 +151,7 @@ public:
*
* @return The number of queued buffers.
*/
u32 GetQueueSize() {
u32 GetQueueSize() const {
return queued_buffers.load();
}
+11 -28
View File
@@ -14,34 +14,11 @@ if (DEFINED ENV{DISPLAYVERSION})
set(DISPLAY_VERSION $ENV{DISPLAYVERSION})
endif ()
# Pass the path to git to the GenerateSCMRev.cmake as well
find_package(Git QUIET)
add_custom_command(OUTPUT scm_rev.cpp
COMMAND ${CMAKE_COMMAND}
-DSRC_DIR=${CMAKE_SOURCE_DIR}
-DBUILD_REPOSITORY=${BUILD_REPOSITORY}
-DTITLE_BAR_FORMAT_IDLE=${TITLE_BAR_FORMAT_IDLE}
-DTITLE_BAR_FORMAT_RUNNING=${TITLE_BAR_FORMAT_RUNNING}
-DBUILD_TAG=${BUILD_TAG}
-DBUILD_ID=${DISPLAY_VERSION}
-DGIT_REF_SPEC=${GIT_REF_SPEC}
-DGIT_REV=${GIT_REV}
-DGIT_DESC=${GIT_DESC}
-DGIT_BRANCH=${GIT_BRANCH}
-DBUILD_FULLNAME=${BUILD_FULLNAME}
-DGIT_EXECUTABLE=${GIT_EXECUTABLE}
-P ${CMAKE_SOURCE_DIR}/CMakeModules/GenerateSCMRev.cmake
DEPENDS
# Check that the scm_rev files haven't changed
"${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.cpp.in"
"${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.h"
# technically we should regenerate if the git version changed, but its not worth the effort imo
"${CMAKE_SOURCE_DIR}/CMakeModules/GenerateSCMRev.cmake"
VERBATIM
)
include(GenerateSCMRev)
add_library(common STATIC
address_space.cpp
address_space.h
algorithm.h
alignment.h
announce_multiplayer_room.h
@@ -106,6 +83,8 @@ add_library(common STATIC
microprofile.cpp
microprofile.h
microprofileui.h
multi_level_page_table.cpp
multi_level_page_table.h
nvidia_flags.cpp
nvidia_flags.h
page_table.cpp
@@ -117,7 +96,7 @@ add_library(common STATIC
quaternion.h
reader_writer_queue.h
ring_buffer.h
scm_rev.cpp
${CMAKE_CURRENT_BINARY_DIR}/scm_rev.cpp
scm_rev.h
scope_exit.h
settings.cpp
@@ -190,7 +169,11 @@ endif()
create_target_directory_groups(common)
target_link_libraries(common PUBLIC ${Boost_LIBRARIES} fmt::fmt microprofile Threads::Threads)
target_link_libraries(common PRIVATE lz4::lz4)
if (TARGET lz4::lz4)
target_link_libraries(common PRIVATE lz4::lz4)
else()
target_link_libraries(common PRIVATE LZ4::lz4_shared)
endif()
if (TARGET zstd::zstd)
target_link_libraries(common PRIVATE zstd::zstd)
else()
+10
View File
@@ -0,0 +1,10 @@
// SPDX-FileCopyrightText: 2021 Skyline Team and Contributors
// SPDX-License-Identifier: GPL-3.0-or-later
#include "common/address_space.inc"
namespace Common {
template class Common::FlatAllocator<u32, 0, 32>;
}
+150
View File
@@ -0,0 +1,150 @@
// SPDX-FileCopyrightText: 2021 Skyline Team and Contributors
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <concepts>
#include <functional>
#include <mutex>
#include <vector>
#include "common/common_types.h"
namespace Common {
template <typename VaType, size_t AddressSpaceBits>
concept AddressSpaceValid = std::is_unsigned_v<VaType> && sizeof(VaType) * 8 >= AddressSpaceBits;
struct EmptyStruct {};
/**
* @brief FlatAddressSpaceMap provides a generic VA->PA mapping implementation using a sorted vector
*/
template <typename VaType, VaType UnmappedVa, typename PaType, PaType UnmappedPa,
bool PaContigSplit, size_t AddressSpaceBits, typename ExtraBlockInfo = EmptyStruct>
requires AddressSpaceValid<VaType, AddressSpaceBits>
class FlatAddressSpaceMap {
public:
/// The maximum VA that this AS can technically reach
static constexpr VaType VaMaximum{(1ULL << (AddressSpaceBits - 1)) +
((1ULL << (AddressSpaceBits - 1)) - 1)};
explicit FlatAddressSpaceMap(VaType va_limit,
std::function<void(VaType, VaType)> unmap_callback = {});
FlatAddressSpaceMap() = default;
void Map(VaType virt, PaType phys, VaType size, ExtraBlockInfo extra_info = {}) {
std::scoped_lock lock(block_mutex);
MapLocked(virt, phys, size, extra_info);
}
void Unmap(VaType virt, VaType size) {
std::scoped_lock lock(block_mutex);
UnmapLocked(virt, size);
}
VaType GetVALimit() const {
return va_limit;
}
protected:
/**
* @brief Represents a block of memory in the AS, the physical mapping is contiguous until
* another block with a different phys address is hit
*/
struct Block {
/// VA of the block
VaType virt{UnmappedVa};
/// PA of the block, will increase 1-1 with VA until a new block is encountered
PaType phys{UnmappedPa};
[[no_unique_address]] ExtraBlockInfo extra_info;
Block() = default;
Block(VaType virt_, PaType phys_, ExtraBlockInfo extra_info_)
: virt(virt_), phys(phys_), extra_info(extra_info_) {}
bool Valid() const {
return virt != UnmappedVa;
}
bool Mapped() const {
return phys != UnmappedPa;
}
bool Unmapped() const {
return phys == UnmappedPa;
}
bool operator<(const VaType& p_virt) const {
return virt < p_virt;
}
};
/**
* @brief Maps a PA range into the given AS region
* @note block_mutex MUST be locked when calling this
*/
void MapLocked(VaType virt, PaType phys, VaType size, ExtraBlockInfo extra_info);
/**
* @brief Unmaps the given range and merges it with other unmapped regions
* @note block_mutex MUST be locked when calling this
*/
void UnmapLocked(VaType virt, VaType size);
std::mutex block_mutex;
std::vector<Block> blocks{Block{}};
/// a soft limit on the maximum VA of the AS
VaType va_limit{VaMaximum};
private:
/// Callback called when the mappings in an region have changed
std::function<void(VaType, VaType)> unmap_callback{};
};
/**
* @brief FlatMemoryManager specialises FlatAddressSpaceMap to work as an allocator, with an
* initial, fast linear pass and a subsequent slower pass that iterates until it finds a free block
*/
template <typename VaType, VaType UnmappedVa, size_t AddressSpaceBits>
requires AddressSpaceValid<VaType, AddressSpaceBits>
class FlatAllocator
: public FlatAddressSpaceMap<VaType, UnmappedVa, bool, false, false, AddressSpaceBits> {
private:
using Base = FlatAddressSpaceMap<VaType, UnmappedVa, bool, false, false, AddressSpaceBits>;
public:
explicit FlatAllocator(VaType virt_start, VaType va_limit = Base::VaMaximum);
/**
* @brief Allocates a region in the AS of the given size and returns its address
*/
VaType Allocate(VaType size);
/**
* @brief Marks the given region in the AS as allocated
*/
void AllocateFixed(VaType virt, VaType size);
/**
* @brief Frees an AS region so it can be used again
*/
void Free(VaType virt, VaType size);
VaType GetVAStart() const {
return virt_start;
}
private:
/// The base VA of the allocator, no allocations will be below this
VaType virt_start;
/**
* The end address for the initial linear allocation pass
* Once this reaches the AS limit the slower allocation path will be used
*/
VaType current_linear_alloc_end;
};
} // namespace Common
+366
View File
@@ -0,0 +1,366 @@
// SPDX-FileCopyrightText: 2021 Skyline Team and Contributors
// SPDX-License-Identifier: GPL-3.0-or-later
#include "common/address_space.h"
#include "common/assert.h"
#define MAP_MEMBER(returnType) \
template <typename VaType, VaType UnmappedVa, typename PaType, PaType UnmappedPa, \
bool PaContigSplit, size_t AddressSpaceBits, typename ExtraBlockInfo> \
requires AddressSpaceValid<VaType, AddressSpaceBits> returnType FlatAddressSpaceMap< \
VaType, UnmappedVa, PaType, UnmappedPa, PaContigSplit, AddressSpaceBits, ExtraBlockInfo>
#define MAP_MEMBER_CONST() \
template <typename VaType, VaType UnmappedVa, typename PaType, PaType UnmappedPa, \
bool PaContigSplit, size_t AddressSpaceBits, typename ExtraBlockInfo> \
requires AddressSpaceValid<VaType, AddressSpaceBits> FlatAddressSpaceMap< \
VaType, UnmappedVa, PaType, UnmappedPa, PaContigSplit, AddressSpaceBits, ExtraBlockInfo>
#define MM_MEMBER(returnType) \
template <typename VaType, VaType UnmappedVa, size_t AddressSpaceBits> \
requires AddressSpaceValid<VaType, AddressSpaceBits> returnType \
FlatMemoryManager<VaType, UnmappedVa, AddressSpaceBits>
#define ALLOC_MEMBER(returnType) \
template <typename VaType, VaType UnmappedVa, size_t AddressSpaceBits> \
requires AddressSpaceValid<VaType, AddressSpaceBits> returnType \
FlatAllocator<VaType, UnmappedVa, AddressSpaceBits>
#define ALLOC_MEMBER_CONST() \
template <typename VaType, VaType UnmappedVa, size_t AddressSpaceBits> \
requires AddressSpaceValid<VaType, AddressSpaceBits> \
FlatAllocator<VaType, UnmappedVa, AddressSpaceBits>
namespace Common {
MAP_MEMBER_CONST()::FlatAddressSpaceMap(VaType va_limit_,
std::function<void(VaType, VaType)> unmap_callback_)
: va_limit{va_limit_}, unmap_callback{std::move(unmap_callback_)} {
if (va_limit > VaMaximum) {
ASSERT_MSG(false, "Invalid VA limit!");
}
}
MAP_MEMBER(void)::MapLocked(VaType virt, PaType phys, VaType size, ExtraBlockInfo extra_info) {
VaType virt_end{virt + size};
if (virt_end > va_limit) {
ASSERT_MSG(false,
"Trying to map a block past the VA limit: virt_end: 0x{:X}, va_limit: 0x{:X}",
virt_end, va_limit);
}
auto block_end_successor{std::lower_bound(blocks.begin(), blocks.end(), virt_end)};
if (block_end_successor == blocks.begin()) {
ASSERT_MSG(false, "Trying to map a block before the VA start: virt_end: 0x{:X}", virt_end);
}
auto block_end_predecessor{std::prev(block_end_successor)};
if (block_end_successor != blocks.end()) {
// We have blocks in front of us, if one is directly in front then we don't have to add a
// tail
if (block_end_successor->virt != virt_end) {
PaType tailPhys{[&]() -> PaType {
if constexpr (!PaContigSplit) {
// Always propagate unmapped regions rather than calculating offset
return block_end_predecessor->phys;
} else {
if (block_end_predecessor->Unmapped()) {
// Always propagate unmapped regions rather than calculating offset
return block_end_predecessor->phys;
} else {
return block_end_predecessor->phys + virt_end - block_end_predecessor->virt;
}
}
}()};
if (block_end_predecessor->virt >= virt) {
// If this block's start would be overlapped by the map then reuse it as a tail
// block
block_end_predecessor->virt = virt_end;
block_end_predecessor->phys = tailPhys;
block_end_predecessor->extra_info = block_end_predecessor->extra_info;
// No longer predecessor anymore
block_end_successor = block_end_predecessor--;
} else {
// Else insert a new one and we're done
blocks.insert(block_end_successor,
{Block(virt, phys, extra_info),
Block(virt_end, tailPhys, block_end_predecessor->extra_info)});
if (unmap_callback) {
unmap_callback(virt, size);
}
return;
}
}
} else {
// block_end_predecessor will always be unmapped as blocks has to be terminated by an
// unmapped chunk
if (block_end_predecessor != blocks.begin() && block_end_predecessor->virt >= virt) {
// Move the unmapped block start backwards
block_end_predecessor->virt = virt_end;
// No longer predecessor anymore
block_end_successor = block_end_predecessor--;
} else {
// Else insert a new one and we're done
blocks.insert(block_end_successor,
{Block(virt, phys, extra_info), Block(virt_end, UnmappedPa, {})});
if (unmap_callback) {
unmap_callback(virt, size);
}
return;
}
}
auto block_start_successor{block_end_successor};
// Walk the block vector to find the start successor as this is more efficient than another
// binary search in most scenarios
while (std::prev(block_start_successor)->virt >= virt) {
block_start_successor--;
}
// Check that the start successor is either the end block or something in between
if (block_start_successor->virt > virt_end) {
ASSERT_MSG(false, "Unsorted block in AS map: virt: 0x{:X}", block_start_successor->virt);
} else if (block_start_successor->virt == virt_end) {
// We need to create a new block as there are none spare that we would overwrite
blocks.insert(block_start_successor, Block(virt, phys, extra_info));
} else {
// Erase overwritten blocks
if (auto eraseStart{std::next(block_start_successor)}; eraseStart != block_end_successor) {
blocks.erase(eraseStart, block_end_successor);
}
// Reuse a block that would otherwise be overwritten as a start block
block_start_successor->virt = virt;
block_start_successor->phys = phys;
block_start_successor->extra_info = extra_info;
}
if (unmap_callback) {
unmap_callback(virt, size);
}
}
MAP_MEMBER(void)::UnmapLocked(VaType virt, VaType size) {
VaType virt_end{virt + size};
if (virt_end > va_limit) {
ASSERT_MSG(false,
"Trying to map a block past the VA limit: virt_end: 0x{:X}, va_limit: 0x{:X}",
virt_end, va_limit);
}
auto block_end_successor{std::lower_bound(blocks.begin(), blocks.end(), virt_end)};
if (block_end_successor == blocks.begin()) {
ASSERT_MSG(false, "Trying to unmap a block before the VA start: virt_end: 0x{:X}",
virt_end);
}
auto block_end_predecessor{std::prev(block_end_successor)};
auto walk_back_to_predecessor{[&](auto iter) {
while (iter->virt >= virt) {
iter--;
}
return iter;
}};
auto erase_blocks_with_end_unmapped{[&](auto unmappedEnd) {
auto block_start_predecessor{walk_back_to_predecessor(unmappedEnd)};
auto block_start_successor{std::next(block_start_predecessor)};
auto eraseEnd{[&]() {
if (block_start_predecessor->Unmapped()) {
// If the start predecessor is unmapped then we can erase everything in our region
// and be done
return std::next(unmappedEnd);
} else {
// Else reuse the end predecessor as the start of our unmapped region then erase all
// up to it
unmappedEnd->virt = virt;
return unmappedEnd;
}
}()};
// We can't have two unmapped regions after each other
if (eraseEnd != blocks.end() &&
(eraseEnd == block_start_successor ||
(block_start_predecessor->Unmapped() && eraseEnd->Unmapped()))) {
ASSERT_MSG(false, "Multiple contiguous unmapped regions are unsupported!");
}
blocks.erase(block_start_successor, eraseEnd);
}};
// We can avoid any splitting logic if these are the case
if (block_end_predecessor->Unmapped()) {
if (block_end_predecessor->virt > virt) {
erase_blocks_with_end_unmapped(block_end_predecessor);
}
if (unmap_callback) {
unmap_callback(virt, size);
}
return; // The region is unmapped, bail out early
} else if (block_end_successor->virt == virt_end && block_end_successor->Unmapped()) {
erase_blocks_with_end_unmapped(block_end_successor);
if (unmap_callback) {
unmap_callback(virt, size);
}
return; // The region is unmapped here and doesn't need splitting, bail out early
} else if (block_end_successor == blocks.end()) {
// This should never happen as the end should always follow an unmapped block
ASSERT_MSG(false, "Unexpected Memory Manager state!");
} else if (block_end_successor->virt != virt_end) {
// If one block is directly in front then we don't have to add a tail
// The previous block is mapped so we will need to add a tail with an offset
PaType tailPhys{[&]() {
if constexpr (PaContigSplit) {
return block_end_predecessor->phys + virt_end - block_end_predecessor->virt;
} else {
return block_end_predecessor->phys;
}
}()};
if (block_end_predecessor->virt >= virt) {
// If this block's start would be overlapped by the unmap then reuse it as a tail block
block_end_predecessor->virt = virt_end;
block_end_predecessor->phys = tailPhys;
// No longer predecessor anymore
block_end_successor = block_end_predecessor--;
} else {
blocks.insert(block_end_successor,
{Block(virt, UnmappedPa, {}),
Block(virt_end, tailPhys, block_end_predecessor->extra_info)});
if (unmap_callback) {
unmap_callback(virt, size);
}
// The previous block is mapped and ends before
return;
}
}
// Walk the block vector to find the start predecessor as this is more efficient than another
// binary search in most scenarios
auto block_start_predecessor{walk_back_to_predecessor(block_end_successor)};
auto block_start_successor{std::next(block_start_predecessor)};
if (block_start_successor->virt > virt_end) {
ASSERT_MSG(false, "Unsorted block in AS map: virt: 0x{:X}", block_start_successor->virt);
} else if (block_start_successor->virt == virt_end) {
// There are no blocks between the start and the end that would let us skip inserting a new
// one for head
// The previous block is may be unmapped, if so we don't need to insert any unmaps after it
if (block_start_predecessor->Mapped()) {
blocks.insert(block_start_successor, Block(virt, UnmappedPa, {}));
}
} else if (block_start_predecessor->Unmapped()) {
// If the previous block is unmapped
blocks.erase(block_start_successor, block_end_predecessor);
} else {
// Erase overwritten blocks, skipping the first one as we have written the unmapped start
// block there
if (auto eraseStart{std::next(block_start_successor)}; eraseStart != block_end_successor) {
blocks.erase(eraseStart, block_end_successor);
}
// Add in the unmapped block header
block_start_successor->virt = virt;
block_start_successor->phys = UnmappedPa;
}
if (unmap_callback)
unmap_callback(virt, size);
}
ALLOC_MEMBER_CONST()::FlatAllocator(VaType virt_start_, VaType va_limit_)
: Base{va_limit_}, virt_start{virt_start_}, current_linear_alloc_end{virt_start_} {}
ALLOC_MEMBER(VaType)::Allocate(VaType size) {
std::scoped_lock lock(this->block_mutex);
VaType alloc_start{UnmappedVa};
VaType alloc_end{current_linear_alloc_end + size};
// Avoid searching backwards in the address space if possible
if (alloc_end >= current_linear_alloc_end && alloc_end <= this->va_limit) {
auto alloc_end_successor{
std::lower_bound(this->blocks.begin(), this->blocks.end(), alloc_end)};
if (alloc_end_successor == this->blocks.begin()) {
ASSERT_MSG(false, "First block in AS map is invalid!");
}
auto alloc_end_predecessor{std::prev(alloc_end_successor)};
if (alloc_end_predecessor->virt <= current_linear_alloc_end) {
alloc_start = current_linear_alloc_end;
} else {
// Skip over fixed any mappings in front of us
while (alloc_end_successor != this->blocks.end()) {
if (alloc_end_successor->virt - alloc_end_predecessor->virt < size ||
alloc_end_predecessor->Mapped()) {
alloc_start = alloc_end_predecessor->virt;
break;
}
alloc_end_predecessor = alloc_end_successor++;
// Use the VA limit to calculate if we can fit in the final block since it has no
// successor
if (alloc_end_successor == this->blocks.end()) {
alloc_end = alloc_end_predecessor->virt + size;
if (alloc_end >= alloc_end_predecessor->virt && alloc_end <= this->va_limit) {
alloc_start = alloc_end_predecessor->virt;
}
}
}
}
}
if (alloc_start != UnmappedVa) {
current_linear_alloc_end = alloc_start + size;
} else { // If linear allocation overflows the AS then find a gap
if (this->blocks.size() <= 2) {
ASSERT_MSG(false, "Unexpected allocator state!");
}
auto search_predecessor{this->blocks.begin()};
auto search_successor{std::next(search_predecessor)};
while (search_successor != this->blocks.end() &&
(search_successor->virt - search_predecessor->virt < size ||
search_predecessor->Mapped())) {
search_predecessor = search_successor++;
}
if (search_successor != this->blocks.end()) {
alloc_start = search_predecessor->virt;
} else {
return {}; // AS is full
}
}
this->MapLocked(alloc_start, true, size, {});
return alloc_start;
}
ALLOC_MEMBER(void)::AllocateFixed(VaType virt, VaType size) {
this->Map(virt, true, size);
}
ALLOC_MEMBER(void)::Free(VaType virt, VaType size) {
this->Unmap(virt, size);
}
} // namespace Common
+8
View File
@@ -24,4 +24,12 @@ template <class ForwardIt, class T, class Compare = std::less<>>
return first != last && !comp(value, *first) ? first : last;
}
template <typename T, typename Func, typename... Args>
T FoldRight(T initial_value, Func&& func, Args&&... args) {
T value{initial_value};
const auto high_func = [&value, &func]<typename U>(U x) { value = func(value, x); };
(std::invoke(high_func, std::forward<Args>(args)), ...);
return value;
}
} // namespace Common
+7
View File
@@ -18,4 +18,11 @@ struct PairHash {
}
};
template <typename T>
struct IdentityHash {
[[nodiscard]] size_t operator()(T value) const noexcept {
return static_cast<size_t>(value);
}
};
} // namespace Common
+29 -1
View File
@@ -76,6 +76,19 @@ enum class PollingError {
Unknown,
};
// Nfc reply from the controller
enum class NfcState {
Success,
NewAmiibo,
WaitingForAmiibo,
AmiiboRemoved,
NotAnAmiibo,
NotSupported,
WrongDeviceState,
WriteFailed,
Unknown,
};
// Ir camera reply from the controller
enum class CameraError {
None,
@@ -202,6 +215,11 @@ struct CameraStatus {
std::vector<u8> data{};
};
struct NfcStatus {
NfcState state{};
std::vector<u8> data{};
};
// List of buttons to be passed to Qt that can be translated
enum class ButtonNames {
Undefined,
@@ -259,7 +277,9 @@ struct CallbackStatus {
BodyColorStatus color_status{};
BatteryStatus battery_status{};
VibrationStatus vibration_status{};
CameraStatus camera_status{};
CameraFormat camera_status{CameraFormat::None};
NfcState nfc_status{NfcState::Unknown};
std::vector<u8> raw_data{};
};
// Triggered once every input change
@@ -312,6 +332,14 @@ public:
virtual CameraError SetCameraFormat([[maybe_unused]] CameraFormat camera_format) {
return CameraError::NotSupported;
}
virtual NfcState SupportsNfc() const {
return NfcState::NotSupported;
}
virtual NfcState WriteNfcData([[maybe_unused]] const std::vector<u8>& data) {
return NfcState::NotSupported;
}
};
/// An abstract class template for a factory that can create input devices.
+1 -1
View File
@@ -219,7 +219,7 @@ private:
void StartBackendThread() {
backend_thread = std::jthread([this](std::stop_token stop_token) {
Common::SetCurrentThreadName("yuzu:Log");
Common::SetCurrentThreadName("Logger");
Entry entry;
const auto write_logs = [this, &entry]() {
ForEachBackend([&entry](Backend& backend) { backend.Write(entry); });
+9
View File
@@ -0,0 +1,9 @@
// SPDX-FileCopyrightText: 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/multi_level_page_table.inc"
namespace Common {
template class Common::MultiLevelPageTable<u64>;
template class Common::MultiLevelPageTable<u32>;
} // namespace Common
+78
View File
@@ -0,0 +1,78 @@
// SPDX-FileCopyrightText: 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <type_traits>
#include <utility>
#include <vector>
#include "common/common_types.h"
namespace Common {
template <typename BaseAddr>
class MultiLevelPageTable final {
public:
constexpr MultiLevelPageTable() = default;
explicit MultiLevelPageTable(std::size_t address_space_bits, std::size_t first_level_bits,
std::size_t page_bits);
~MultiLevelPageTable() noexcept;
MultiLevelPageTable(const MultiLevelPageTable&) = delete;
MultiLevelPageTable& operator=(const MultiLevelPageTable&) = delete;
MultiLevelPageTable(MultiLevelPageTable&& other) noexcept
: address_space_bits{std::exchange(other.address_space_bits, 0)},
first_level_bits{std::exchange(other.first_level_bits, 0)}, page_bits{std::exchange(
other.page_bits, 0)},
first_level_shift{std::exchange(other.first_level_shift, 0)},
first_level_chunk_size{std::exchange(other.first_level_chunk_size, 0)},
first_level_map{std::move(other.first_level_map)}, base_ptr{std::exchange(other.base_ptr,
nullptr)} {}
MultiLevelPageTable& operator=(MultiLevelPageTable&& other) noexcept {
address_space_bits = std::exchange(other.address_space_bits, 0);
first_level_bits = std::exchange(other.first_level_bits, 0);
page_bits = std::exchange(other.page_bits, 0);
first_level_shift = std::exchange(other.first_level_shift, 0);
first_level_chunk_size = std::exchange(other.first_level_chunk_size, 0);
alloc_size = std::exchange(other.alloc_size, 0);
first_level_map = std::move(other.first_level_map);
base_ptr = std::exchange(other.base_ptr, nullptr);
return *this;
}
void ReserveRange(u64 start, std::size_t size);
[[nodiscard]] const BaseAddr& operator[](std::size_t index) const {
return base_ptr[index];
}
[[nodiscard]] BaseAddr& operator[](std::size_t index) {
return base_ptr[index];
}
[[nodiscard]] BaseAddr* data() {
return base_ptr;
}
[[nodiscard]] const BaseAddr* data() const {
return base_ptr;
}
private:
void AllocateLevel(u64 level);
std::size_t address_space_bits{};
std::size_t first_level_bits{};
std::size_t page_bits{};
std::size_t first_level_shift{};
std::size_t first_level_chunk_size{};
std::size_t alloc_size{};
std::vector<void*> first_level_map{};
BaseAddr* base_ptr{};
};
} // namespace Common
+84
View File
@@ -0,0 +1,84 @@
// SPDX-FileCopyrightText: 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/mman.h>
#endif
#include "common/assert.h"
#include "common/multi_level_page_table.h"
namespace Common {
template <typename BaseAddr>
MultiLevelPageTable<BaseAddr>::MultiLevelPageTable(std::size_t address_space_bits_,
std::size_t first_level_bits_,
std::size_t page_bits_)
: address_space_bits{address_space_bits_},
first_level_bits{first_level_bits_}, page_bits{page_bits_} {
if (page_bits == 0) {
return;
}
first_level_shift = address_space_bits - first_level_bits;
first_level_chunk_size = (1ULL << (first_level_shift - page_bits)) * sizeof(BaseAddr);
alloc_size = (1ULL << (address_space_bits - page_bits)) * sizeof(BaseAddr);
std::size_t first_level_size = 1ULL << first_level_bits;
first_level_map.resize(first_level_size, nullptr);
#ifdef _WIN32
void* base{VirtualAlloc(nullptr, alloc_size, MEM_RESERVE, PAGE_READWRITE)};
#else
void* base{mmap(nullptr, alloc_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)};
if (base == MAP_FAILED) {
base = nullptr;
}
#endif
ASSERT(base);
base_ptr = reinterpret_cast<BaseAddr*>(base);
}
template <typename BaseAddr>
MultiLevelPageTable<BaseAddr>::~MultiLevelPageTable() noexcept {
if (!base_ptr) {
return;
}
#ifdef _WIN32
ASSERT(VirtualFree(base_ptr, 0, MEM_RELEASE));
#else
ASSERT(munmap(base_ptr, alloc_size) == 0);
#endif
}
template <typename BaseAddr>
void MultiLevelPageTable<BaseAddr>::ReserveRange(u64 start, std::size_t size) {
const u64 new_start = start >> first_level_shift;
const u64 new_end = (start + size) >> first_level_shift;
for (u64 i = new_start; i <= new_end; i++) {
if (!first_level_map[i]) {
AllocateLevel(i);
}
}
}
template <typename BaseAddr>
void MultiLevelPageTable<BaseAddr>::AllocateLevel(u64 level) {
void* ptr = reinterpret_cast<char *>(base_ptr) + level * first_level_chunk_size;
#ifdef _WIN32
void* base{VirtualAlloc(ptr, first_level_chunk_size, MEM_COMMIT, PAGE_READWRITE)};
#else
void* base{mmap(ptr, first_level_chunk_size, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)};
if (base == MAP_FAILED) {
base = nullptr;
}
#endif
ASSERT(base);
first_level_map[level] = base;
}
} // namespace Common
+3 -1
View File
@@ -431,7 +431,7 @@ struct Values {
FullscreenMode::Exclusive,
#endif
FullscreenMode::Borderless, FullscreenMode::Exclusive, "fullscreen_mode"};
SwitchableSetting<int, true> aspect_ratio{0, 0, 3, "aspect_ratio"};
SwitchableSetting<int, true> aspect_ratio{0, 0, 4, "aspect_ratio"};
SwitchableSetting<int, true> max_anisotropy{0, 0, 5, "max_anisotropy"};
SwitchableSetting<bool> use_speed_limit{true, "use_speed_limit"};
SwitchableSetting<u16, true> speed_limit{100, 0, 9999, "speed_limit"};
@@ -530,6 +530,8 @@ struct Values {
Setting<bool> use_debug_asserts{false, "use_debug_asserts"};
Setting<bool> use_auto_stub{false, "use_auto_stub"};
Setting<bool> enable_all_controllers{false, "enable_all_controllers"};
Setting<bool> create_crash_dumps{false, "create_crash_dumps"};
Setting<bool> perform_vulkan_check{true, "perform_vulkan_check"};
// Miscellaneous
Setting<std::string> log_filter{"*:Info", "log_filter"};
+4
View File
@@ -54,6 +54,10 @@ public:
is_set = false;
}
[[nodiscard]] bool IsSet() {
return is_set;
}
private:
std::condition_variable condvar;
std::mutex mutex;
+16 -10
View File
@@ -4,12 +4,6 @@
add_library(core STATIC
arm/arm_interface.h
arm/arm_interface.cpp
arm/dynarmic/arm_dynarmic_32.cpp
arm/dynarmic/arm_dynarmic_32.h
arm/dynarmic/arm_dynarmic_64.cpp
arm/dynarmic/arm_dynarmic_64.h
arm/dynarmic/arm_dynarmic_cp15.cpp
arm/dynarmic/arm_dynarmic_cp15.h
arm/dynarmic/arm_exclusive_monitor.cpp
arm/dynarmic/arm_exclusive_monitor.h
arm/exclusive_monitor.cpp
@@ -144,8 +138,6 @@ add_library(core STATIC
frontend/emu_window.h
frontend/framebuffer_layout.cpp
frontend/framebuffer_layout.h
hardware_interrupt_manager.cpp
hardware_interrupt_manager.h
hid/emulated_console.cpp
hid/emulated_console.h
hid/emulated_controller.cpp
@@ -466,6 +458,8 @@ add_library(core STATIC
hle/service/hid/controllers/mouse.h
hle/service/hid/controllers/npad.cpp
hle/service/hid/controllers/npad.h
hle/service/hid/controllers/palma.cpp
hle/service/hid/controllers/palma.h
hle/service/hid/controllers/stubbed.cpp
hle/service/hid/controllers/stubbed.h
hle/service/hid/controllers/touchscreen.cpp
@@ -500,6 +494,8 @@ add_library(core STATIC
hle/service/jit/jit.h
hle/service/lbl/lbl.cpp
hle/service/lbl/lbl.h
hle/service/ldn/lan_discovery.cpp
hle/service/ldn/lan_discovery.h
hle/service/ldn/ldn_results.h
hle/service/ldn/ldn.cpp
hle/service/ldn/ldn.h
@@ -525,8 +521,14 @@ add_library(core STATIC
hle/service/ncm/ncm.h
hle/service/nfc/nfc.cpp
hle/service/nfc/nfc.h
hle/service/nfp/amiibo_crypto.cpp
hle/service/nfp/amiibo_crypto.h
hle/service/nfp/nfp.cpp
hle/service/nfp/nfp.h
hle/service/nfp/nfp_device.cpp
hle/service/nfp/nfp_device.h
hle/service/nfp/nfp_result.h
hle/service/nfp/nfp_types.h
hle/service/nfp/nfp_user.cpp
hle/service/nfp/nfp_user.h
hle/service/ngct/ngct.cpp
@@ -546,6 +548,12 @@ add_library(core STATIC
hle/service/ns/ns.h
hle/service/ns/pdm_qry.cpp
hle/service/ns/pdm_qry.h
hle/service/nvdrv/core/container.cpp
hle/service/nvdrv/core/container.h
hle/service/nvdrv/core/nvmap.cpp
hle/service/nvdrv/core/nvmap.h
hle/service/nvdrv/core/syncpoint_manager.cpp
hle/service/nvdrv/core/syncpoint_manager.h
hle/service/nvdrv/devices/nvdevice.h
hle/service/nvdrv/devices/nvdisp_disp0.cpp
hle/service/nvdrv/devices/nvdisp_disp0.h
@@ -574,8 +582,6 @@ add_library(core STATIC
hle/service/nvdrv/nvdrv_interface.h
hle/service/nvdrv/nvmemp.cpp
hle/service/nvdrv/nvmemp.h
hle/service/nvdrv/syncpoint_manager.cpp
hle/service/nvdrv/syncpoint_manager.h
hle/service/nvflinger/binder.h
hle/service/nvflinger/buffer_item.h
hle/service/nvflinger/buffer_item_consumer.cpp
+8 -7
View File
@@ -27,7 +27,6 @@
#include "core/file_sys/savedata_factory.h"
#include "core/file_sys/vfs_concat.h"
#include "core/file_sys/vfs_real.h"
#include "core/hardware_interrupt_manager.h"
#include "core/hid/hid_core.h"
#include "core/hle/kernel/k_memory_manager.h"
#include "core/hle/kernel/k_process.h"
@@ -51,6 +50,7 @@
#include "core/telemetry_session.h"
#include "core/tools/freezer.h"
#include "network/network.h"
#include "video_core/host1x/host1x.h"
#include "video_core/renderer_base.h"
#include "video_core/video_core.h"
@@ -215,6 +215,7 @@ struct System::Impl {
telemetry_session = std::make_unique<Core::TelemetrySession>();
host1x_core = std::make_unique<Tegra::Host1x::Host1x>(system);
gpu_core = VideoCore::CreateGPU(emu_window, system);
if (!gpu_core) {
return SystemResultStatus::ErrorVideoCore;
@@ -224,7 +225,6 @@ struct System::Impl {
service_manager = std::make_shared<Service::SM::ServiceManager>(kernel);
services = std::make_unique<Service::Services>(service_manager, system);
interrupt_manager = std::make_unique<Hardware::InterruptManager>(system);
// Initialize time manager, which must happen after kernel is created
time_manager.Initialize();
@@ -373,6 +373,7 @@ struct System::Impl {
app_loader.reset();
audio_core.reset();
gpu_core.reset();
host1x_core.reset();
perf_stats.reset();
kernel.Shutdown();
memory.Reset();
@@ -450,7 +451,7 @@ struct System::Impl {
/// AppLoader used to load the current executing application
std::unique_ptr<Loader::AppLoader> app_loader;
std::unique_ptr<Tegra::GPU> gpu_core;
std::unique_ptr<Hardware::InterruptManager> interrupt_manager;
std::unique_ptr<Tegra::Host1x::Host1x> host1x_core;
std::unique_ptr<Core::DeviceMemory> device_memory;
std::unique_ptr<AudioCore::AudioCore> audio_core;
Core::Memory::Memory memory;
@@ -668,12 +669,12 @@ const Tegra::GPU& System::GPU() const {
return *impl->gpu_core;
}
Core::Hardware::InterruptManager& System::InterruptManager() {
return *impl->interrupt_manager;
Tegra::Host1x::Host1x& System::Host1x() {
return *impl->host1x_core;
}
const Core::Hardware::InterruptManager& System::InterruptManager() const {
return *impl->interrupt_manager;
const Tegra::Host1x::Host1x& System::Host1x() const {
return *impl->host1x_core;
}
VideoCore::RendererBase& System::Renderer() {
+9 -10
View File
@@ -74,6 +74,9 @@ class TimeManager;
namespace Tegra {
class DebugContext;
class GPU;
namespace Host1x {
class Host1x;
} // namespace Host1x
} // namespace Tegra
namespace VideoCore {
@@ -88,10 +91,6 @@ namespace Core::Timing {
class CoreTiming;
}
namespace Core::Hardware {
class InterruptManager;
}
namespace Core::HID {
class HIDCore;
}
@@ -260,6 +259,12 @@ public:
/// Gets an immutable reference to the GPU interface.
[[nodiscard]] const Tegra::GPU& GPU() const;
/// Gets a mutable reference to the Host1x interface
[[nodiscard]] Tegra::Host1x::Host1x& Host1x();
/// Gets an immutable reference to the Host1x interface.
[[nodiscard]] const Tegra::Host1x::Host1x& Host1x() const;
/// Gets a mutable reference to the renderer.
[[nodiscard]] VideoCore::RendererBase& Renderer();
@@ -296,12 +301,6 @@ public:
/// Provides a constant reference to the core timing instance.
[[nodiscard]] const Timing::CoreTiming& CoreTiming() const;
/// Provides a reference to the interrupt manager instance.
[[nodiscard]] Core::Hardware::InterruptManager& InterruptManager();
/// Provides a constant reference to the interrupt manager instance.
[[nodiscard]] const Core::Hardware::InterruptManager& InterruptManager() const;
/// Provides a reference to the kernel instance.
[[nodiscard]] Kernel::KernelCore& Kernel();
+43 -18
View File
@@ -43,7 +43,7 @@ CoreTiming::CoreTiming()
CoreTiming::~CoreTiming() = default;
void CoreTiming::ThreadEntry(CoreTiming& instance) {
constexpr char name[] = "yuzu:HostTiming";
constexpr char name[] = "HostTiming";
MicroProfileOnThreadCreate(name);
Common::SetCurrentThreadName(name);
Common::SetCurrentThreadPriority(Common::ThreadPriority::Critical);
@@ -134,13 +134,17 @@ void CoreTiming::ScheduleLoopingEvent(std::chrono::nanoseconds start_time,
std::chrono::nanoseconds resched_time,
const std::shared_ptr<EventType>& event_type,
std::uintptr_t user_data, bool absolute_time) {
std::scoped_lock scope{basic_lock};
const auto next_time{absolute_time ? start_time : GetGlobalTimeNs() + start_time};
{
std::scoped_lock scope{basic_lock};
const auto next_time{absolute_time ? start_time : GetGlobalTimeNs() + start_time};
event_queue.emplace_back(
Event{next_time.count(), event_fifo_id++, user_data, event_type, resched_time.count()});
event_queue.emplace_back(
Event{next_time.count(), event_fifo_id++, user_data, event_type, resched_time.count()});
std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>());
std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>());
}
event.Set();
}
void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type,
@@ -229,17 +233,17 @@ std::optional<s64> CoreTiming::Advance() {
basic_lock.lock();
if (evt.reschedule_time != 0) {
// If this event was scheduled into a pause, its time now is going to be way behind.
// Re-set this event to continue from the end of the pause.
auto next_time{evt.time + evt.reschedule_time};
if (evt.time < pause_end_time) {
next_time = pause_end_time + evt.reschedule_time;
}
const auto next_schedule_time{new_schedule_time.has_value()
? new_schedule_time.value().count()
: evt.reschedule_time};
// If this event was scheduled into a pause, its time now is going to be way behind.
// Re-set this event to continue from the end of the pause.
auto next_time{evt.time + next_schedule_time};
if (evt.time < pause_end_time) {
next_time = pause_end_time + next_schedule_time;
}
event_queue.emplace_back(
Event{next_time, event_fifo_id++, evt.user_data, evt.type, next_schedule_time});
std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>());
@@ -250,8 +254,7 @@ std::optional<s64> CoreTiming::Advance() {
}
if (!event_queue.empty()) {
const s64 next_time = event_queue.front().time - global_timer;
return next_time;
return event_queue.front().time;
} else {
return std::nullopt;
}
@@ -264,11 +267,33 @@ void CoreTiming::ThreadLoop() {
paused_set = false;
const auto next_time = Advance();
if (next_time) {
if (*next_time > 0) {
std::chrono::nanoseconds next_time_ns = std::chrono::nanoseconds(*next_time);
event.WaitFor(next_time_ns);
// There are more events left in the queue, wait until the next event.
const auto wait_time = *next_time - GetGlobalTimeNs().count();
if (wait_time > 0) {
#ifdef _WIN32
// Assume a timer resolution of 1ms.
static constexpr s64 TimerResolutionNS = 1000000;
// Sleep in discrete intervals of the timer resolution, and spin the rest.
const auto sleep_time = wait_time - (wait_time % TimerResolutionNS);
if (sleep_time > 0) {
event.WaitFor(std::chrono::nanoseconds(sleep_time));
}
while (!paused && !event.IsSet() && GetGlobalTimeNs().count() < *next_time) {
// Yield to reduce thread starvation.
std::this_thread::yield();
}
if (event.IsSet()) {
event.Reset();
}
#else
event.WaitFor(std::chrono::nanoseconds(wait_time));
#endif
}
} else {
// Queue is empty, wait until another event is scheduled and signals us to continue.
wait_set = true;
event.Wait();
}
+2 -2
View File
@@ -189,9 +189,9 @@ void CpuManager::RunThread(std::size_t core) {
system.RegisterCoreThread(core);
std::string name;
if (is_multicore) {
name = "yuzu:CPUCore_" + std::to_string(core);
name = "CPUCore_" + std::to_string(core);
} else {
name = "yuzu:CPUThread";
name = "CPUThread";
}
MicroProfileOnThreadCreate(name.c_str());
Common::SetCurrentThreadName(name.c_str());
+1 -1
View File
@@ -140,7 +140,7 @@ private:
}
void ThreadLoop(std::stop_token stop_token) {
Common::SetCurrentThreadName("yuzu:Debugger");
Common::SetCurrentThreadName("Debugger");
// Set up the client signals for new data.
AsyncReceiveInto(signal_pipe, pipe_data, [&](auto d) { PipeData(d); });
+47 -5
View File
@@ -33,11 +33,55 @@ Loader::ResultStatus ProgramMetadata::Load(VirtualFile file) {
return Loader::ResultStatus::ErrorBadACIHeader;
}
if (sizeof(FileAccessControl) != file->ReadObject(&acid_file_access, acid_header.fac_offset)) {
// Load acid_file_access per-component instead of the entire struct, since this struct does not
// reflect the layout of the real data.
std::size_t current_offset = acid_header.fac_offset;
if (sizeof(FileAccessControl::version) != file->ReadBytes(&acid_file_access.version,
sizeof(FileAccessControl::version),
current_offset)) {
return Loader::ResultStatus::ErrorBadFileAccessControl;
}
if (sizeof(FileAccessControl::permissions) !=
file->ReadBytes(&acid_file_access.permissions, sizeof(FileAccessControl::permissions),
current_offset += sizeof(FileAccessControl::version) + 3)) {
return Loader::ResultStatus::ErrorBadFileAccessControl;
}
if (sizeof(FileAccessControl::unknown) !=
file->ReadBytes(&acid_file_access.unknown, sizeof(FileAccessControl::unknown),
current_offset + sizeof(FileAccessControl::permissions))) {
return Loader::ResultStatus::ErrorBadFileAccessControl;
}
if (sizeof(FileAccessHeader) != file->ReadObject(&aci_file_access, aci_header.fah_offset)) {
// Load aci_file_access per-component instead of the entire struct, same as acid_file_access
current_offset = aci_header.fah_offset;
if (sizeof(FileAccessHeader::version) != file->ReadBytes(&aci_file_access.version,
sizeof(FileAccessHeader::version),
current_offset)) {
return Loader::ResultStatus::ErrorBadFileAccessHeader;
}
if (sizeof(FileAccessHeader::permissions) !=
file->ReadBytes(&aci_file_access.permissions, sizeof(FileAccessHeader::permissions),
current_offset += sizeof(FileAccessHeader::version) + 3)) {
return Loader::ResultStatus::ErrorBadFileAccessHeader;
}
if (sizeof(FileAccessHeader::unk_offset) !=
file->ReadBytes(&aci_file_access.unk_offset, sizeof(FileAccessHeader::unk_offset),
current_offset += sizeof(FileAccessHeader::permissions))) {
return Loader::ResultStatus::ErrorBadFileAccessHeader;
}
if (sizeof(FileAccessHeader::unk_size) !=
file->ReadBytes(&aci_file_access.unk_size, sizeof(FileAccessHeader::unk_size),
current_offset += sizeof(FileAccessHeader::unk_offset))) {
return Loader::ResultStatus::ErrorBadFileAccessHeader;
}
if (sizeof(FileAccessHeader::unk_offset_2) !=
file->ReadBytes(&aci_file_access.unk_offset_2, sizeof(FileAccessHeader::unk_offset_2),
current_offset += sizeof(FileAccessHeader::unk_size))) {
return Loader::ResultStatus::ErrorBadFileAccessHeader;
}
if (sizeof(FileAccessHeader::unk_size_2) !=
file->ReadBytes(&aci_file_access.unk_size_2, sizeof(FileAccessHeader::unk_size_2),
current_offset + sizeof(FileAccessHeader::unk_offset_2))) {
return Loader::ResultStatus::ErrorBadFileAccessHeader;
}
@@ -152,9 +196,7 @@ void ProgramMetadata::Print() const {
LOG_DEBUG(Service_FS, " > Is Retail: {}", acid_header.is_retail ? "YES" : "NO");
LOG_DEBUG(Service_FS, "Title ID Min: 0x{:016X}", acid_header.title_id_min);
LOG_DEBUG(Service_FS, "Title ID Max: 0x{:016X}", acid_header.title_id_max);
u64_le permissions_l; // local copy to fix alignment error
std::memcpy(&permissions_l, &acid_file_access.permissions, sizeof(permissions_l));
LOG_DEBUG(Service_FS, "Filesystem Access: 0x{:016X}\n", permissions_l);
LOG_DEBUG(Service_FS, "Filesystem Access: 0x{:016X}\n", acid_file_access.permissions);
// Begin ACI0 printing (actual perms, unsigned)
LOG_DEBUG(Service_FS, "Magic: {:.4}", aci_header.magic.data());
+4 -10
View File
@@ -144,20 +144,18 @@ private:
static_assert(sizeof(AciHeader) == 0x40, "ACI0 header structure size is wrong");
#pragma pack(push, 1)
// FileAccessControl and FileAccessHeader need loaded per-component: this layout does not
// reflect the real layout to avoid reference binding to misaligned addresses
struct FileAccessControl {
u8 version;
INSERT_PADDING_BYTES(3);
// 3 padding bytes
u64_le permissions;
std::array<u8, 0x20> unknown;
};
static_assert(sizeof(FileAccessControl) == 0x2C, "FS access control structure size is wrong");
struct FileAccessHeader {
u8 version;
INSERT_PADDING_BYTES(3);
// 3 padding bytes
u64_le permissions;
u32_le unk_offset;
u32_le unk_size;
@@ -165,10 +163,6 @@ private:
u32_le unk_size_2;
};
static_assert(sizeof(FileAccessHeader) == 0x1C, "FS access header structure size is wrong");
#pragma pack(pop)
Header npdm_header;
AciHeader aci_header;
AcidHeader acid_header;
+2
View File
@@ -67,6 +67,8 @@ float EmulationAspectRatio(AspectRatio aspect, float window_aspect_ratio) {
return 3.0f / 4.0f;
case AspectRatio::R21_9:
return 9.0f / 21.0f;
case AspectRatio::R16_10:
return 10.0f / 16.0f;
case AspectRatio::StretchToWindow:
return window_aspect_ratio;
default:
+1
View File
@@ -27,6 +27,7 @@ enum class AspectRatio {
Default,
R4_3,
R21_9,
R16_10,
StretchToWindow,
};
-32
View File
@@ -1,32 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hardware_interrupt_manager.h"
#include "core/hle/service/nvdrv/nvdrv_interface.h"
#include "core/hle/service/sm/sm.h"
namespace Core::Hardware {
InterruptManager::InterruptManager(Core::System& system_in) : system(system_in) {
gpu_interrupt_event = Core::Timing::CreateEvent(
"GPUInterrupt",
[this](std::uintptr_t message, u64 time,
std::chrono::nanoseconds) -> std::optional<std::chrono::nanoseconds> {
auto nvdrv = system.ServiceManager().GetService<Service::Nvidia::NVDRV>("nvdrv");
const u32 syncpt = static_cast<u32>(message >> 32);
const u32 value = static_cast<u32>(message);
nvdrv->SignalGPUInterruptSyncpt(syncpt, value);
return std::nullopt;
});
}
InterruptManager::~InterruptManager() = default;
void InterruptManager::GPUInterruptSyncpt(const u32 syncpoint_id, const u32 value) {
const u64 msg = (static_cast<u64>(syncpoint_id) << 32ULL) | value;
system.CoreTiming().ScheduleEvent(std::chrono::nanoseconds{10}, gpu_interrupt_event, msg);
}
} // namespace Core::Hardware

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