Compare commits

...

253 Commits

Author SHA1 Message Date
Liam f1a0ce0e70 memory: fix watchpoint use when fastmem is enabled 2023-01-15 10:24:31 -05:00
bunnei 0e8f98a441 Merge pull request #9605 from german77/mouse_mapping
yuzu: Read mouse scroll
2023-01-10 17:32:58 -08:00
Narr the Reg 87b02f78e1 yuzu: Read mouse wheel input 2023-01-10 18:20:58 -06:00
Morph c277dad25f Merge pull request #9596 from liamwhite/mvk
MoltenVK: restrict number of vertex attributes/bindings to 16
2023-01-10 18:11:44 -05:00
liamwhite cbcf210c19 Merge pull request #9582 from yuzu-emu/revert-9518-revert-9504-pg2
Revert "Revert "k_page_group: synchronize""
2023-01-10 15:27:33 -05:00
liamwhite 0eae0b6803 Merge pull request #9601 from liamwhite/it-never-ends
qt: unlock during signal emission
2023-01-10 15:27:12 -05:00
liamwhite 74404261d2 Merge pull request #9598 from liamwhite/indirect
vulkan_common: fix indirect draw with count
2023-01-10 15:27:02 -05:00
liamwhite e2c68edd35 Merge pull request #9595 from liamwhite/per-game
qt: fix configuration weirdness on turbo
2023-01-10 15:26:49 -05:00
liamwhite 9f974ea818 Merge pull request #9565 from MonsterDruide1/tas-multiplayer-lengths
TAS: Show all script lengths for multiplayer
2023-01-10 15:26:36 -05:00
Liam 385ddef8c3 qt: unlock during signal emission 2023-01-10 12:46:01 -05:00
Liam fa8581e900 vulkan_common: fix indirect draw with count 2023-01-10 09:43:36 -05:00
TellowKrinkle eaf425bd32 MoltenVK: restrict number of vertex attributes/bindings to 16 2023-01-09 19:01:09 -05:00
Liam 1caa84e652 qt: fix configuration weirdness on turbo 2023-01-09 17:54:49 -05:00
UltraHDR fda0e7e989 macOS: Make Yuzu show up in the Launchpad Games folder (#9594)
https://developer.apple.com/documentation/bundleresources/information_property_list/lsapplicationcategorytype
This makes it show up in the Launchpad Games folder
2023-01-09 16:43:45 -05:00
Morph 6bf1436f5c Merge pull request #9589 from liamwhite/default
renderer_vulkan: disable turbo by default
2023-01-09 16:23:24 -05:00
Morph ffb12f4f9f Merge pull request #9581 from liamwhite/turbo2
renderer_vulkan: pause turbo submissions on inactive queue
2023-01-09 16:23:16 -05:00
Morph a4cd747122 Merge pull request #9530 from liamwhite/vk-feature-init
vulkan_device: refactor feature testing
2023-01-09 16:23:04 -05:00
Morph 3be8312120 Merge pull request #9569 from liamwhite/shutdown-wars
qt: additional fixes for reentrant shutdown
2023-01-09 16:21:27 -05:00
Liam 279005448a vulkan_device: refactor feature testing 2023-01-09 16:12:16 -05:00
Fernando S 948ac976d1 Merge pull request #9583 from FernandoS27/fuck-ogl-already
VideoCore: Fix OGL cache invalidation.
2023-01-08 14:05:29 -05:00
Liam 0df43e4e07 renderer_vulkan: disable turbo by default 2023-01-08 11:38:30 -05:00
Fernando Sahmkow efbb6fe288 VideoCore: Fix OGL cache invalidation. 2023-01-07 21:56:17 -05:00
bunnei a5693afa03 Revert "Revert "k_page_group: synchronize"" 2023-01-07 15:32:10 -08:00
bunnei 66e4a48b75 Merge pull request #9563 from german77/crash_not_allowed
input_common: Create an update engine
2023-01-07 13:41:27 -08:00
MonsterDruide1 115bf20448 TAS: Show all script lengths for multiplayer 2023-01-07 21:15:37 +01:00
liamwhite 926438b68d Merge pull request #9578 from bylaws/patch-2
Avoid OOB array access reading passthrough attr mask
2023-01-07 15:14:08 -05:00
Liam c19c8ac92c renderer_vulkan: pause turbo submissions on inactive queue 2023-01-07 14:35:11 -05:00
Billy Laws d34275a260 Avoid OOB array access reading passthrough attr mask
YFC 1.5 extended the size of the varying mask used to hold passthrough attrs without considering this
2023-01-07 18:38:21 +00:00
Narr the Reg 432d48d9c8 Merge pull request #9570 from liamwhite/less-clock-boost
renderer_vulkan: disable clock boost on unvalidated devices
2023-01-07 10:41:37 -06:00
Narr the Reg cc92b7fd94 Merge pull request #9573 from liamwhite/optional
vulkan_device: avoid attempt to access empty optional
2023-01-07 10:40:21 -06:00
Liam 444b25bae1 vulkan_device: avoid attempt to access empty optional 2023-01-06 21:23:21 -05:00
Liam 2e4dde12c7 renderer_vulkan: disable clock boost on unvalidated devices 2023-01-06 19:07:47 -05:00
Liam 9ed4c13758 qt: additional fixes for reentrant shutdown 2023-01-06 18:50:01 -05:00
liamwhite c0f17e1b27 Merge pull request #9567 from german77/antialias
opengl: Sanitize antialiasing config
2023-01-06 15:20:23 -05:00
Narr the Reg 4bda2b475f opengl: Sanitize antialiasing config 2023-01-06 13:42:20 -06:00
Fernando S 7ef897a277 Merge pull request #9566 from Wollnashorn/vulkan-cache-header-fix
video_core/vulkan: Fixed loading of Vulkan driver pipeline cache
2023-01-06 11:58:36 -05:00
Wollnashorn 457826a83b video_core/vulkan: Fixed loading of Vulkan driver pipeline cache
The header size of the Vulkan driver pipeline cache files was incorrectly in PipelineCache::LoadVulkanPipelineCache, for which the pipeline cache wasn't read correctly and got invalidated on each load.
2023-01-06 16:52:41 +01:00
Fernando S 8b251fc3f6 Merge pull request #9535 from bylaws/master
Port over several shader-compiler fixes from skyline
2023-01-06 10:06:45 -05:00
liamwhite 3c05988df2 Merge pull request #9561 from liamwhite/update-dynarmic
externals: update dynarmic, xbyak
2023-01-06 10:00:18 -05:00
liamwhite 6d74490139 Merge pull request #9558 from MonsterDruide1/network-timeout-noerror
net: Silently translate ETIMEDOUT network error
2023-01-06 10:00:09 -05:00
liamwhite 020dbcdbc7 Merge pull request #9552 from liamwhite/turbo
vulkan: implement 'turbo mode' clock booster
2023-01-06 09:59:59 -05:00
Fernando S 5bcbb8de45 Merge pull request #9559 from FernandoS27/cached-writes
VideoCore: Implement Cached Writes, use fastmem for reading GPU memory and eliminate old stuffs
2023-01-06 07:31:39 -05:00
liamwhite 990fe2b3fc Merge pull request #9564 from FernandoS27/oops-i-did-it-again
MacroHLE: eliminate 2 rushed macros.
2023-01-05 22:14:27 -05:00
Fernando Sahmkow f6245dc40a MacroHLE: eliminate 2 rushed macros. 2023-01-05 20:53:31 -05:00
Narr the Reg 8042ce7e19 input_common: Create an update engine 2023-01-05 19:24:29 -06:00
liamwhite eaca61e073 Merge pull request #9528 from liamwhite/mvk-nulldesc
renderer_vulkan: implement fallback path for null buffer descriptors
2023-01-05 18:31:55 -05:00
liamwhite 3e33a878dc Merge pull request #9536 from liamwhite/debug-utils
vulkan_common: unify VK_EXT_debug_utils and selection of validation layer
2023-01-05 18:31:45 -05:00
Liam 1ee0540f82 externals: update dynarmic, xbyak 2023-01-05 18:06:06 -05:00
Billy Laws 58fec43768 Run clang-format 2023-01-05 22:18:10 +00:00
Billy Laws 12b4c9c04c externals: Update sirit 2023-01-05 22:13:07 +00:00
Billy Laws 68ed60cee4 shader_recompiler: Fix shuffle partitioning for >64 invoc-per-subgroup GPUs
The existing implementation only supports 64 invoc-per-subgroup GPUs, and misbehaves on adreno when invocations need to be split into 4 emulated subgroups.
2023-01-05 22:13:07 +00:00
Billy Laws 6c812a0c84 Vulkan, OpenGL: Hook up geometry shader passthrough emulation 2023-01-05 22:13:07 +00:00
Billy Laws 625a4af73a shader_recompiler: Add support for lowering geometry passthrough
Reuses most of the existing code for generating the gl_Layer passthrough. Fixes geometry in Nier: Automata on GPUs without HW passthrough support.
2023-01-05 22:13:07 +00:00
Billy Laws 9e2997c4b6 Vulkan, OpenGL: Hook up storage buffer alignment code 2023-01-05 22:13:07 +00:00
Billy Laws 8804a4eb23 shader_recompiler: Align SSBO offsets to meet host requirements
We can take advantage of SSBO addresses being passed in a constant bufer to account for the extra alignment requirements in the shader itself.
2023-01-05 22:13:07 +00:00
Billy Laws 3f0985c7b0 shader_recompiler: SPIRV: Only enable int64 feature when supported 2023-01-05 22:13:07 +00:00
Billy Laws c1cc99584c shader_recompiler: Add comparison operators to descriptor types 2023-01-05 22:13:07 +00:00
Billy Laws bbfad79c89 Vulkan: Add a workaround for input_position on Adreno drivers
Adreno drivers will crash compiling geometry shaders if the input position is not wrapped in a gl_in struct.
2023-01-05 22:13:07 +00:00
Fernando S 1428451722 Merge pull request #9527 from Wollnashorn/amd-cache-fix
video_core/vulkan: Implemented `VkPipelineCache` to store Vulkan pipelines
2023-01-05 16:38:07 -05:00
Wollnashorn e07976a22b video_core/vulkan: Vulkan driver pipelines now contain cache version
So that old cache can get deleted when the cache version changes and does not grow infinitely
2023-01-05 21:03:01 +01:00
Wollnashorn 9c9008ac81 video_core/vulkan: Driver pipeline cache will now be deleted with the shader cache 2023-01-05 21:03:01 +01:00
Wollnashorn 8945fafcc0 config: Set the Vulkan driver pipeline cache option to be global 2023-01-05 21:03:01 +01:00
Wollnashorn f2aa816679 video_core/vulkan: Added check if Vulkan pipeline path has been set 2023-01-05 21:03:01 +01:00
Wollnashorn f4626512ff config: Better wording for VK pipeline cache option and enable by default 2023-01-05 21:03:01 +01:00
Wollnashorn 67d4f190f7 yuzu-cmd: Removed use_vulkan_driver_pipeline_cache from default_ini.h
The addition of the use_vulkan_driver_pipeline_cache option into the default ini string literal caused the 16,384-byte limit of the MSVC compiler to be exceeded.
2023-01-05 21:03:01 +01:00
Wollnashorn 16809c1fa7 video_core/vulkan: Added VkPipelineCache to store Vulkan pipelines
As an optional feature which can be enabled in the advanced graphics configuration, all pipelines that get built at the initial shader loading are stored in a VkPipelineCache object and are dumped to the disk.

These vendor specific pipeline cache files are located at `/shader/GAME_ID/vulkan_pipelines.bin`. This feature was mainly added because of an issue with the AMD driver (see yuzu-emu#8507) causing invalidation of the cache files the driver builds automatically.
2023-01-05 21:02:44 +01:00
Fernando Sahmkow b56ad93bbc BufferBase: Don't ignore GPU pages. 2023-01-05 14:00:10 -05:00
Fernando Sahmkow 2d0c4f2b1d Fermi2D: sync cache flushes 2023-01-05 06:43:28 -05:00
Fernando Sahmkow af5ecb0b15 MemoryManager: use fastmem directly. 2023-01-05 06:06:33 -05:00
MonsterDruide1 688a9fbfa6 net: Silently translate ETIMEDOUT network error 2023-01-05 11:54:36 +01:00
Fernando Sahmkow 6c7eb81f7d video_core: Cache GPU internal writes. 2023-01-05 05:23:39 -05:00
liamwhite e82e3e06be Merge pull request #9557 from FernandoS27/ooops-i-killed-the-shitty-drivers
Vulkan: Fix drivers that don't support dynamic_state_2 up
2023-01-05 00:14:01 -05:00
Fernando Sahmkow 4d9af4a9d2 Vulkan: Fix drivers that don't support dynamic_state_2 up 2023-01-05 00:11:16 -05:00
Liam a4269c285a common: add setting for renderer clock workaround 2023-01-04 22:22:01 -05:00
Liam 301e9bbc03 vulkan: implement 'turbo mode' clock booster 2023-01-04 22:22:01 -05:00
Liam 66ae79de13 renderer_vulkan: implement fallback path for null descriptors 2023-01-04 22:14:01 -05:00
liamwhite b78328f19a Merge pull request #9501 from FernandoS27/yfc-rel-2
Yuzu Fried Chicken Part 1.5: MacroHLE Rework and Dynamic State
2023-01-04 21:20:00 -05:00
Fernando Sahmkow 3ecc03ec1b yuzu-ui: Add setting for disabling macro HLE 2023-01-04 14:56:52 -05:00
Fernando Sahmkow a0c697124c Video_core: Address feedback 2023-01-04 14:39:42 -05:00
Fernando Sahmkow 03ccd8bf43 Texture Cache: Implement async texture downloads. 2023-01-03 22:52:15 -05:00
liamwhite bbeb6e460c Merge pull request #9518 from gidoly/revert-9504-pg2
Revert "k_page_group: synchronize"
2023-01-03 21:40:57 -05:00
Fernando Sahmkow ddbf851ef6 Vulkan: Update blacklisting to latest driver versions. 2023-01-03 21:16:43 -05:00
Fernando Sahmkow a045e860dd ShaderCompiler: Inline driver specific constants. 2023-01-03 16:29:25 -05:00
Fernando Sahmkow b62ffb612d Vulkan: rework stencil tracking. 2023-01-03 16:29:16 -05:00
liamwhite 6f031f08fe Merge pull request #9547 from MonsterDruide1/tas-doesnt-flap
TAS: Immediately switch stick to TAS on input
2023-01-03 15:03:58 -05:00
MonsterDruide1 04cb05fce0 TAS: Immediately switch stick to TAS on input
Co-Authored-By: Narr the Reg <5944268+german77@users.noreply.github.com>
2023-01-03 20:08:25 +01:00
liamwhite a7e610403d Merge pull request #9542 from abouvier/cmake-module-path
cmake: move find-modules to root cmake dir
2023-01-02 13:45:36 -05:00
Alexandre Bouvier eceee8c3d9 cmake: move find-modules to root cmake dir 2023-01-02 18:22:07 +01:00
liamwhite 2b110d61e7 Merge pull request #9541 from abouvier/cmake-option
cmake: allow options shadowing with normal variables
2023-01-02 11:29:32 -05:00
liamwhite 6804a43f49 Merge pull request #9540 from MonsterDruide1/tas-sanitized-record
TAS: Record sanitized instead of raw stick inputs
2023-01-02 09:51:29 -05:00
bunnei 48bcb91a2e Merge pull request #9537 from abouvier/cmake-almost-quiet
cmake: improve find_package failure messages
2023-01-02 01:08:20 -08:00
bunnei 09c9be3703 Merge pull request #9543 from german77/nifm
service: nifm: Initialize request state
2023-01-01 21:38:43 -08:00
german77 80bcc18788 service: nifm: Initialize request state 2023-01-01 20:58:08 -06:00
german77 ebd811b535 service: nifm: Match documentation names 2023-01-01 20:58:01 -06:00
Alexandre Bouvier 306c791e67 cmake: allow options shadowing with normal variables 2023-01-02 02:43:38 +01:00
Alexandre Bouvier 1dfcf19c36 cmake: improve find_package failure messages 2023-01-02 02:27:25 +01:00
Liam f9c6d39a6c vulkan_common: blacklist radv from extended_dynamic_state2 on drivers before 22.3.1 2023-01-01 16:43:58 -05:00
Liam 4814d87385 video_core: fix build 2023-01-01 16:43:58 -05:00
Fernando Sahmkow d09aa0182f MacroHLE: Final cleanup and fixes. 2023-01-01 16:43:58 -05:00
Fernando Sahmkow 581a7d785b Rasterizer: Setup skeleton for Host Conditional rendering 2023-01-01 16:43:58 -05:00
Fernando Sahmkow 3630bfaef3 RasterizerMemory: Add filtering for flushing/invalidation operations. 2023-01-01 16:43:58 -05:00
Fernando Sahmkow 2793304117 Vulkan: Allow stagging buffer deferrals. 2023-01-01 16:43:58 -05:00
Fernando Sahmkow 8d694701bc MacroHLE: Add OpenGL Support 2023-01-01 16:43:58 -05:00
Fernando Sahmkow 4c82e47edd Vulkan: Add other additional pipeline specs 2023-01-01 16:43:58 -05:00
Fernando Sahmkow d33251db93 Vulkan: Implement Dynamic State 3 2023-01-01 16:43:58 -05:00
Fernando Sahmkow f800e485c9 Vulkan Implement Dynamic State 2 LogicOp and PatchVertices 2023-01-01 16:43:58 -05:00
Fernando Sahmkow c897c55e3c Vulkan: Implement Dynamic States 2 2023-01-01 16:43:57 -05:00
Fernando Sahmkow cb1497d0d7 DMAPusher: Improve collection of non executing methods 2023-01-01 16:43:57 -05:00
Fernando Sahmkow ce448ce770 Revert Buffer cache changes and setup additional macros. 2023-01-01 16:43:57 -05:00
Fernando Sahmkow 18637766ef MacroHLE: Reduce massive calculations on sizing estimation. 2023-01-01 16:43:57 -05:00
Fernando Sahmkow aad0cbf024 MacroHLE: Add HLE replacement for base vertex and base instance. 2023-01-01 16:43:57 -05:00
Fernando Sahmkow 93ac5a6a6d MacroHLE: Add Index Buffer size estimation. 2023-01-01 16:43:57 -05:00
Fernando Sahmkow c541559767 MacroHLE: Refactor MacroHLE system. 2023-01-01 16:43:57 -05:00
Fernando Sahmkow 0f89828073 MacroHLE: Implement DrawIndexedIndirect & DrawArraysIndirect. 2023-01-01 16:43:57 -05:00
Fernando Sahmkow a5a94f52ff MacroHLE: Add MultidrawIndirect HLE Macro. 2023-01-01 16:43:57 -05:00
MonsterDruide1 d46c9c4659 TAS: Record sanitized instead of raw stick inputs
Co-Authored-By: Narr the Reg <5944268+german77@users.noreply.github.com>
2023-01-01 22:39:18 +01:00
Mai a12a4f2a13 Merge pull request #9538 from merryhime/char-concat
vfs: Replace cstr concat with char concat
2023-01-01 20:00:46 +00:00
Merry bee395d2f0 vfs: Replace cstr concat with char concat 2023-01-01 18:52:02 +00:00
Liam aa13ee5c4a vulkan_common: unify VK_EXT_debug_utils and selection of validation layer 2023-01-01 11:59:47 -05:00
liamwhite 92103d4ff3 Merge pull request #9533 from merryhime/overcommit
host_memory: mmap changes for virtual_base
2023-01-01 10:24:07 -05:00
liamwhite b2d8bbe0e0 Merge pull request #9532 from zhaobot/tx-update-20230101024213
Update translations (2023-01-01)
2023-01-01 10:23:55 -05:00
liamwhite 0b228fde15 Merge pull request #9514 from ColinKinloch/en_gb
settings: warn on invalid regon/language combinations
2023-01-01 10:23:46 -05:00
Merry fd1831b65b host_memory: Use transparent huge pages where available 2023-01-01 11:40:35 +00:00
Merry 4d7be85e73 host_memory: Allocate virtual_base with MAP_NORESERVE
Specify that we do not require swap to be reserved for this address range;
allow overcommitting.
2023-01-01 11:40:35 +00:00
The yuzu Community 72722986d0 Update translations (2023-01-01) 2023-01-01 02:42:48 +00:00
liamwhite 88f5d38b93 Merge pull request #9526 from ColinKinloch/choose_clang_format
ci: Allow setting clang-format binary
2022-12-30 15:20:20 -05:00
Colin Kinloch 5d36d4b143 ci: Allow setting clang-format binary 2022-12-30 14:29:41 +00:00
Colin Kinloch 28cfc2146f settings: comment language blocklist columns 2022-12-30 13:51:35 +00:00
bunnei 0ac34bd058 Merge pull request #9524 from bunnei/touch-button-crash-fix
core: hid: emulated_console: Avoid a crash if frontend does not configure touch_from_button_maps.
2022-12-30 03:26:41 -05:00
bunnei 05c709bebe core: hid: emulated_console: Avoid a crash if frontend does not configure touch_from_button_maps. 2022-12-30 00:14:53 -08:00
bunnei c3af6d8372 Merge pull request #9515 from liamwhite/cmake-refactor
CMake: make more features optional
2022-12-29 23:37:25 -05:00
Narr the Reg 73167b12b5 Merge pull request #9521 from Wollnashorn/global-only-multiplayer-settings
config: Save multiplayer settings only globally
2022-12-29 22:22:48 -06:00
Wollnashorn 1df5d12b19 config: Save multiplayer settings only globally
Saved multiplayer settings like the nickname, remote address, etc. were reset everytime a game was booted up and the game-specific config files were loaded, as these values will never be set.
2022-12-30 02:32:58 +01:00
Colin Kinloch 8594f287b8 settings: added regon/language warning bounds check 2022-12-29 15:55:24 +00:00
gidoly 10eaf31af3 Revert "k_page_group: synchronize" 2022-12-29 17:39:42 +09:00
liamwhite 9fdacb5e3a Merge pull request #9423 from vonchenplus/vulkan_quad_strip
video_core: Implement all vulkan topology
2022-12-28 20:59:23 -05:00
Liam 9ce23bde24 cmake: make Vulkan-Headers external the default 2022-12-28 20:55:32 -05:00
Liam c18cf05a06 cmake: make cubeb and SDL2 optional 2022-12-28 17:29:32 -05:00
bunnei 60419dd35e Merge pull request #9504 from liamwhite/pg2
k_page_group: synchronize
2022-12-28 17:28:31 -05:00
Liam be43b62d79 cmake: make libusb optional 2022-12-28 17:26:46 -05:00
Liam 3c2aa183a1 cmake: ignore missing package finders for packages with submodule fallbacks 2022-12-28 17:21:31 -05:00
Liam 106cf27135 cmake: make room server optional 2022-12-28 17:18:27 -05:00
Colin Kinloch 2ccf175324 settings: warn on invalid regon/language combinations 2022-12-28 20:34:28 +00:00
bunnei c5de54d509 Merge pull request #9490 from ameerj/texture-cache-prealloc
texture_cache: Use pre-allocated heap buffer for texture swizzles
2022-12-27 00:07:35 -05:00
bunnei 343c01b87a Merge pull request #9495 from german77/no_refresh
yuzu: Automatically refresh device list
2022-12-27 00:07:13 -05:00
Mai 2d7f9fb21b Merge pull request #9507 from abouvier/patch-1
tests: add missing header
2022-12-26 07:19:08 +00:00
Alexandre Bouvier dce2649daf tests: add missing header
<cstring> is needed for std::memcpy
2022-12-26 04:26:31 +00:00
FengChen 6a397bc8ed video_core: Implement other missing vulkan topology 2022-12-26 12:20:49 +08:00
FengChen 86d5b4e556 video_core: Implement vulkan QuadStrip topology 2022-12-26 11:37:34 +08:00
Narr the Reg ac00ead7d4 Merge pull request #9489 from MonsterDruide1/tas-stick-deadzone
TAS: Increase accuracy of Stick inputs
2022-12-25 17:47:50 -06:00
MonsterDruide1 bc4126acd7 TAS: Increase accuracy of Stick inputs 2022-12-25 21:49:09 +01:00
ameerj 7584d36922 texture_cache: Use Common::ScratchBuffer for swizzle buffers 2022-12-25 15:47:41 -05:00
ameerj 1209d428f1 texture_cache: Use pre-allocated buffer for texture downloads 2022-12-25 15:38:36 -05:00
ameerj c448b3af2f texture_cache: Use pre-allocated buffer for texture uploads 2022-12-25 15:38:36 -05:00
Liam 28d9c30861 k_page_table: remove HACK_OpenPages/ClosePages 2022-12-25 13:43:49 -05:00
Liam 3392fdac9b k_page_group: synchronize 2022-12-25 12:55:21 -05:00
liamwhite 9933121256 Merge pull request #9500 from liamwhite/reentrant-shutdown
qt: prevent reentrant shutdown
2022-12-25 12:51:25 -05:00
liamwhite c6767704fb Merge pull request #9496 from liamwhite/shm3
kernel: workaround static shared memory initialization
2022-12-25 12:51:16 -05:00
liamwhite ea70d9c79e Merge pull request #9487 from liamwhite/look-at-the-time
time: add LockFreeAtomicType
2022-12-25 12:50:57 -05:00
Fernando S 3e6850f00b Merge pull request #9453 from ameerj/scratch-vector
common: Add ScratchBuffer Class
2022-12-24 20:26:06 -05:00
Liam cb7f0c2ec3 qt: prevent reentrant shutdown 2022-12-24 17:31:34 -05:00
liamwhite c86e21abe4 qt: fix 'Pause' menu item (#9497) 2022-12-23 21:44:53 -05:00
Chris Oboe 201733d1b5 Disable automatically opening the console on windows yuzu-cmd builds (#9485)
* don't automatically open the console on windows build of yuzu-cmd

* fix formatting
2022-12-23 21:39:59 -05:00
liamwhite db15142ac9 Merge pull request #9476 from liamwhite/async-shutdown
qt: continue event loop during game close
2022-12-23 21:05:10 -05:00
Morph fa231645f2 Merge pull request #9486 from liamwhite/shutdown-hell
qt: exit properly on guest-initiated close
2022-12-23 21:03:58 -05:00
Liam 646656412f qt: fix uninitialized memory usage 2022-12-23 20:57:36 -05:00
german77 c3a5522830 yuzu: Automatically refresh device list 2022-12-23 18:26:48 -06:00
Liam 99eccf581e kernel: workaround static shared memory initialization 2022-12-23 13:40:30 -05:00
Liam 80670a5b6c time: add LockFreeAtomicType 2022-12-21 22:36:55 -05:00
Liam 60ce34aa80 qt: exit properly on guest-initiated close 2022-12-21 19:55:01 -05:00
Liam ae6015a69b qt: use main window as close overlay parent 2022-12-21 19:27:11 -05:00
Liam 053ad04d3f qt: continue event loop during game close 2022-12-20 09:16:08 -05:00
liamwhite 1b11e0f0d3 Merge pull request #9463 from liamwhite/manager-events
EmuThread: refactor
2022-12-20 09:10:41 -05:00
Mai fe126f993d Merge pull request #9482 from liamwhite/vkbump
CMakeLists: bump required Vulkan package version to 1.3.238
2022-12-20 04:01:13 +00:00
ameerj c6590ad07b scratch_buffer: Explicitly defing resize and resize_destructive functions
resize keeps previous data intact when the buffer grows
resize_destructive destroys the previous data when the buffer grows
2022-12-19 22:40:50 -05:00
Liam 9f199c8b0b CMakeLists: bump required Vulkan package version to 1.3.238 2022-12-19 21:57:46 -05:00
liamwhite 6cb6b2da8e Merge pull request #9480 from jbeich/vk-238
externals: update Vulkan-Headers to v1.3.238 to fix -Werror=switch with system package
2022-12-19 18:16:41 -05:00
ameerj 64869807e2 tests: Add ScratchBuffer tests 2022-12-19 18:08:04 -05:00
ameerj 61e4f2d931 dma_pusher: Rework command_headers usage
Uses ScratchBuffer and avoids overwriting the command_headers buffer with the prefetch_command_list
2022-12-19 18:08:04 -05:00
ameerj bdef22ff85 buffer_cache: Use Common::ScratchBuffer for ImmediateBuffer usage 2022-12-19 18:08:04 -05:00
ameerj 4bc2d82130 video_core: Add usages of ScratchBuffer 2022-12-19 18:08:04 -05:00
ameerj cfc34dd41d common: Add ScratchBuffer class
This class creates a default initialized heap allocated buffer for cases where value initializing members during allocation or resize
is redundant.
2022-12-19 18:07:51 -05:00
ameerj 88ba5a7f22 common: add make_unique_for_overwrite 2022-12-19 18:07:42 -05:00
Matías Locatti e44d1fe73c Merge pull request #9474 from liamwhite/timer
kernel: add KHardwareTimer
2022-12-19 18:37:34 -03:00
Jan Beich b60a93a936 externals: update Vulkan-Headers to v1.3.238 2022-12-19 17:14:29 +00:00
liamwhite 42d81aab32 Merge pull request #9471 from german77/input
input_common: Cleanup project
2022-12-19 11:09:00 -05:00
liamwhite 864c8e4b2f Merge pull request #9477 from Morph1984/overlaydialog
overlay_dialog: Hide button dialog box when both buttons are hidden
2022-12-19 09:22:56 -05:00
Morph 690a4c9438 overlay_dialog: Avoid starting the input thread if non-interactive 2022-12-19 00:00:03 -05:00
Morph 190ded7f48 overlay_dialog: Hide button dialog box when both buttons are hidden
This allows for the creation of a non-interactive dialog overlay to display system messages.
2022-12-18 23:54:56 -05:00
Liam c770f25ccb kernel: remove TimeManager 2022-12-18 20:21:24 -05:00
Liam 67c0d714c5 kernel: add KHardwareTimer 2022-12-18 16:37:19 -05:00
german77 cf01a507fb input_common: Cleanup project 2022-12-18 15:33:11 -06:00
liamwhite fcc93a445f Merge pull request #9470 from german77/silenceIkillYou
service: nfc: Silence ListDevices
2022-12-18 15:11:13 -05:00
german77 79f1f326c7 service: nfc: Silence ListDevices 2022-12-18 11:57:33 -06:00
liamwhite 2724ffd6e3 Merge pull request #9469 from Rubo3/patch-1
Use execlp instead of execl to avoid failure
2022-12-18 11:46:43 -05:00
liamwhite ee71404d71 Merge pull request #9467 from german77/folder
yuzu: Remember last selected directory
2022-12-18 10:21:33 -05:00
liamwhite dcc8abf254 Merge pull request #9466 from german77/fix_errors
yuzu: Fix compile and setting errors
2022-12-18 10:21:23 -05:00
Marco Rubin 56b0f979eb Use execlp instead of execl to avoid failure 2022-12-18 14:03:26 +00:00
german77 c218c7d4da yuzu: Remember last selected directory 2022-12-18 00:37:06 -06:00
german77 f999d268f9 bootmanager: Use proper camera size 2022-12-18 00:13:18 -06:00
german77 c489cbee29 bootmanager: Encapsulate all QCamera code 2022-12-17 23:54:47 -06:00
german77 dffeca66fa yuzu: fix device name setting 2022-12-17 23:54:36 -06:00
Matías Locatti fd1ea0fd84 Enable compiler optimizations and enforce x86-64-v2 on GCC/Clang (#9442)
* Testing LTO (#4)

* Testing LTO

* clang

* linux

* Added the rest of Blinkhawk's optimizations

* Unlikely asserts

* Removing LTO from Linux builds - GCC

* Removing LTO from Linux builds - Clang
2022-12-17 17:16:52 -08:00
bunnei 48108a8c9b Merge pull request #9456 from german77/virtual_gamepad
input_common: Add virtual gamepad
2022-12-17 17:16:13 -08:00
Liam 92ce241d4d qt: use _exit instead of exit on SIGINT 2022-12-17 16:26:25 -05:00
Liam d3123079e8 EmuThread: refactor 2022-12-17 16:26:24 -05:00
liamwhite 5da72a891f Merge pull request #7450 from FernandoS27/ndc-vulkan
Vulkan: Add support for VK_EXT_depth_clip_control.
2022-12-17 16:08:10 -05:00
Mai f8a7d6a0ae Merge pull request #9461 from liamwhite/wanative
qt: avoid setting WA_DontCreateNativeAncestors on all platforms
2022-12-17 21:07:01 +00:00
Mai da31326c17 Merge pull request #9454 from liamwhite/wayland-egl
qt: handle wayland-egl platform name
2022-12-17 21:05:46 +00:00
Liam 45672d43e3 qt: avoid setting WA_DontCreateNativeAncestors on all platforms 2022-12-17 10:41:20 -05:00
liamwhite a3bac5550d Merge pull request #9451 from ameerj/camera-data-array
camera: Use pre-allocated vector for camera data
2022-12-17 10:21:50 -05:00
liamwhite 4faea2bbf4 Merge pull request #9452 from ameerj/hle-read-buffer-resreve
hle_ipc: Refactor ReadBuffer to set buffer size upon initialization
2022-12-17 10:21:30 -05:00
liamwhite fa10374d39 Merge pull request #9455 from Kelebek1/audio_signal
[audio_core] Signal buffer event on audio in/out system stop
2022-12-17 10:21:19 -05:00
liamwhite 98135dee16 Merge pull request #9457 from Kelebek1/silence_tfb
Remove unimplemented geometry transform feedback log spam
2022-12-17 10:21:05 -05:00
german77 243404bf34 input_common: Add virtual gamepad 2022-12-16 18:26:11 -06:00
ameerj 7bf4bec257 camera: Use pre-allocated vector for camera data
And avoid an unnecessary copy
2022-12-16 18:00:47 -05:00
Kelebek1 f7d95d0a3a Remove unimplemented transform feedback geometry spam, it should be implemented 2022-12-16 22:52:29 +00:00
liamwhite bbb202ceed Merge pull request #6354 from ogniK5377/device-name
Set: Allow setting device nickname
2022-12-16 14:05:00 -05:00
liamwhite 789da737af Merge pull request #9450 from ameerj/hle-ipc-vector-reserve
hle_ipc: Reserve vectors before populating
2022-12-16 11:57:48 -05:00
liamwhite b541a35e27 Merge pull request #9444 from german77/free_threads
kernel: process: Implement GetFreeThreadCount
2022-12-16 11:57:42 -05:00
liamwhite 6bc1a477bf Merge pull request #8605 from devsnek/graceful-shutdown
let games gracefully exit
2022-12-16 11:57:33 -05:00
liamwhite 9bfd4d880e Merge pull request #6769 from lat9nq/create-shortcut-2
yuzu qt, common: Add option to create game shortcuts on Linux
2022-12-16 11:57:16 -05:00
Kelebek1 6a56f42f5d Signal buffer event on audio in/out system stop, and force remove all registered audio buffers 2022-12-16 16:07:24 +00:00
Liam b81caf1879 qt: handle wayland-egl platform name 2022-12-16 08:47:22 -05:00
ameerj b1d633532f hle_ipc: Refactor ReadBuffer to set buffer size upon initialization
Initializing the vector size during initialization is more efficient than a later call to resize()
2022-12-15 23:22:11 -05:00
ameerj 12c0f682e6 hle_ipc: Reserve vectors before populating 2022-12-15 22:30:42 -05:00
Narr the Reg 9ff891ce71 Merge pull request #9431 from liamwhite/sixty-five-oh-two
vulkan_common: declare storageBuffer8BitAccess
2022-12-15 17:52:16 -06:00
Matías Locatti 82d80869fc Merge pull request #9430 from liamwhite/capable
spirv_emit_context: declare GroupNonUniform capability for SubgroupLocalInvocationId
2022-12-15 20:52:05 -03:00
Narr the Reg 20cbf6f3db kernel: svc: Fix duplicated InfoType enum 2022-12-15 14:18:30 -06:00
Narr the Reg dca4f0687a kernel: process: Implement GetFreeThreadCount
Used by Just Dance® 2023 Edition
2022-12-15 13:44:21 -06:00
liamwhite b8c03411e7 Merge pull request #9433 from Tachi107/cmake-is-awful
build: tweak the find modules even more
2022-12-15 12:05:13 -05:00
liamwhite 3ff7a5de1a Merge pull request #7410 from Nefsen402/wayland-fixes
Wayland fixes
2022-12-15 12:05:01 -05:00
Andrea Pappacoda 4447c9a46e build: tweak the find modules even more
As described in
https://github.com/yuzu-emu/yuzu/pull/9395#discussion_r1047456172
checking for PKG_CONFIG_FOUND before calling pkg_search_module() is
unneeded, and some find modules (like FindFFmpeg.cmake) don't do this
already. Consequently, this patch removes these checks.
2022-12-15 11:52:50 +01:00
bunnei e2f32e8c88 Merge pull request #9441 from yuzu-emu/revert-9232-audio-default-thread
Revert "hle: service: audio: Use default service thread."
2022-12-14 14:58:17 -08:00
bunnei beba9c9b61 Revert "hle: service: audio: Use default service thread." 2022-12-14 14:57:33 -08:00
liamwhite a222f02c7a Merge pull request #6688 from yzct12345/valid-intel-max
render_vulkan: Fix validation errors on less compatible Intel GPUs
2022-12-14 15:33:10 -05:00
FernandoS27 0104e28fe4 Vulkan: Add support for VK_EXT_depth_clip_control. 2022-12-13 21:39:18 -05:00
Chloe Marcec c5f519e1e4 Set: Allow setting device nickname 2022-12-13 19:54:17 -05:00
lat9nq 5a5bb91f40 main: Address review feedback
Moves icon path to ~/.local/share/icons, though I'm opting to avoid
using the game title for the icon and desktop entry name as that would
cause filenames such as
"yuzu-cadence-of-hyrule-crypt-of-the-necrodancer-featuring-the-legend-of-zelda-demo.desktop".
2022-12-13 19:23:54 -05:00
Liam 4fce72c902 vulkan_common: declare storageBuffer8BitAccess 2022-12-13 18:28:50 -05:00
Liam 77b0d01639 spirv_emit_context: declare GroupNonUniform capability for SubgroupLocalInvocationId 2022-12-13 18:25:53 -05:00
lat9nq 18bdf45868 yuzu qt: Create shortcuts on Linux
This creates a Desktop Entry file and a PNG icon for the entry when the
user right-clicks a game and selects "Create Shortcut -> Create
{Application,Desktop} Shortcut". This uses the current executable's path
to create the shortcut.

yuzu qt: Add more error checking and OS gating for shortcuts

main: Remove FreeBSD gating for shortcuts

I'm not going to test FreeBSD, so I don't know if they follow
Freedesktop.org or not. I just have to let someone else verify that it
works there and let them enable it.

main: Move shortcut function to its own function

This function should really be in a common library, at least among
frontends.

main: Remove image manip references

main: Fix difference in MinGW and native GCC versions

main: Fix negation in creat shortcut

Addresses review comment

Co-authored-by: Jan Beich <jbeich@FreeBSD.org>

main: Re-enable freedesktop shorcuts for FreeBSD
2022-12-13 16:42:00 -05:00
Alexander Orzechowski 09e3029c11 gl_device: Use a more robust way to use strict context mode
Instead of checking a environment variable which may not actually
exist or is just wrong, ask QT if it's running on the wayland
platform.
2022-12-13 15:01:51 -05:00
Alexander Orzechowski 2221afaf26 OpenGL: Check for threading support
We need this.
2022-12-13 13:23:35 -05:00
Alexander Orzechowski 45fcde817e wayland: Always use exclusive fullscreen
Wayland does not allow clients to choose their own size and position
on the screen. The concept of fullscreening an application by sizing
it to the screen and removing decorations does not exist. Use
exclusive fullscreen instead.
2022-12-13 13:23:35 -05:00
Alexander Orzechowski 29fbce9fe6 RenderWidget: Set WA_DontCreateNativeAncestors
Some windowing systems like wayland are designed to show hardware accellerated
surfaces as subsurfaces and not native windows.
2022-12-13 13:23:35 -05:00
Alexander Orzechowski 5754456292 emu_window_sdl2: Respect hidpi
Use SDL_GL_GetDrawableSize instead of SDL_GetWindowSize which
will return the true size our swapchain needs to be in even
for hidpi displays.
2022-12-13 13:23:35 -05:00
Alexander Orzechowski 3cc3176ad6 video_core/vulkan: Explicity check swapchain size when deciding to recreate
Vulkan for whatever reason does not return VK_ERROR_OUT_OF_DATE_KHR when
the swapchain is the wrong size. Explicity make sure the size is indeed
up to date to workaround this.
2022-12-13 13:23:35 -05:00
Liam d5f53da79d renderer_opengl: refactor context acquire 2022-12-13 13:23:23 -05:00
liamwhite a4696285af Merge pull request #9425 from german77/german_unlimited
yuzu: Make unlimited frame rate non persistent between game boots
2022-12-12 22:16:17 -05:00
Liam 179adee396 emu_thread: properly force shutdown for unresponsive guest programs 2022-12-12 21:38:20 -05:00
Gus Caplan f44c60321e let games gracefully exit 2022-12-12 21:18:32 -05:00
Narr the Reg 0ed80c9818 yuzu: Make unlimited frame rate non persistent between game boots 2022-12-12 19:21:30 -06:00
265 changed files with 25405 additions and 17805 deletions
+1
View File
@@ -11,6 +11,7 @@ ccache -s
mkdir build || true && cd build
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_FLAGS="-march=x86-64-v2" \
-DCMAKE_CXX_COMPILER=/usr/lib/ccache/clang++ \
-DCMAKE_C_COMPILER=/usr/lib/ccache/clang \
-DCMAKE_INSTALL_PREFIX="/usr" \
Regular → Executable
+1 -1
View File
@@ -10,7 +10,7 @@ if grep -nrI '\s$' src *.yml *.txt *.md Doxyfile .gitignore .gitmodules .ci* dis
fi
# Default clang-format points to default 3.5 version one
CLANG_FORMAT=clang-format-12
CLANG_FORMAT=${CLANG_FORMAT:-clang-format-12}
$CLANG_FORMAT --version
if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then
+1
View File
@@ -12,6 +12,7 @@ mkdir build || true && cd build
cmake .. \
-DBoost_USE_STATIC_LIBS=ON \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_FLAGS="-march=x86-64-v2" \
-DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ \
-DCMAKE_C_COMPILER=/usr/lib/ccache/gcc \
-DCMAKE_INSTALL_PREFIX="/usr" \
+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 -DYUZU_CRASH_DUMPS=ON .. && cd ..
- script: refreshenv && mkdir build && cd build && cmake -E env CXXFLAGS="/Gw /GA /Gr /Ob2" cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DCMAKE_POLICY_DEFAULT_CMP0069=NEW -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'
+24 -16
View File
@@ -3,13 +3,8 @@
cmake_minimum_required(VERSION 3.22)
# Dynarmic has cmake_minimum_required(3.12) and we may want to override
# some of its variables, which is only possible in 3.13+
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modules")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/find-modules")
include(DownloadExternals)
include(CMakeDependentOption)
@@ -22,6 +17,8 @@ CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" ON
# On Linux system SDL2 is likely to be lacking HIDAPI support which have drawbacks but is needed for SDL motion
CMAKE_DEPENDENT_OPTION(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" ON "ENABLE_SDL2;NOT MSVC" OFF)
option(ENABLE_LIBUSB "Enable the use of LibUSB" ON)
option(ENABLE_OPENGL "Enable OpenGL" ON)
mark_as_advanced(FORCE ENABLE_OPENGL)
option(ENABLE_QT "Enable the Qt frontend" ON)
@@ -35,6 +32,8 @@ option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)
option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" "${WIN32}")
option(YUZU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" ON)
option(YUZU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF)
option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF)
@@ -47,6 +46,8 @@ option(YUZU_TESTS "Compile tests" ON)
option(YUZU_USE_PRECOMPILED_HEADERS "Use precompiled headers" ON)
option(YUZU_ROOM "Compile LDN room server" 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}")
@@ -201,36 +202,43 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
# System imported libraries
# =======================================================================
find_package(enet 1.3)
# Enforce the search mode of non-required packages for better and shorter failure messages
find_package(enet 1.3 MODULE)
find_package(fmt 9 REQUIRED)
find_package(inih)
find_package(libusb 1.0.24)
find_package(inih MODULE)
find_package(lz4 REQUIRED)
find_package(nlohmann_json 3.8 REQUIRED)
find_package(Opus 1.3)
find_package(Vulkan 1.3.213)
find_package(Opus 1.3 MODULE)
find_package(ZLIB 1.2 REQUIRED)
find_package(zstd 1.5 REQUIRED)
if (NOT YUZU_USE_EXTERNAL_VULKAN_HEADERS)
find_package(Vulkan 1.3.238 REQUIRED)
endif()
if (ENABLE_LIBUSB)
find_package(libusb 1.0.24 MODULE)
endif()
if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64)
find_package(xbyak 6)
find_package(xbyak 6 CONFIG)
endif()
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
find_package(dynarmic 6.4.0)
find_package(dynarmic 6.4.0 CONFIG)
endif()
if (ENABLE_CUBEB)
find_package(cubeb)
find_package(cubeb CONFIG)
endif()
if (USE_DISCORD_PRESENCE)
find_package(DiscordRPC)
find_package(DiscordRPC MODULE)
endif()
if (ENABLE_WEB_SERVICE)
find_package(cpp-jwt 1.4)
find_package(httplib 0.11)
find_package(cpp-jwt 1.4 CONFIG)
find_package(httplib 0.11 MODULE)
endif()
if (YUZU_TESTS)
@@ -2,9 +2,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
find_package(PkgConfig QUIET)
if (PKG_CONFIG_FOUND)
pkg_search_module(OPUS QUIET IMPORTED_TARGET opus)
endif()
pkg_search_module(OPUS QUIET IMPORTED_TARGET opus)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Opus
@@ -3,9 +3,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
find_package(PkgConfig QUIET)
if (PKG_CONFIG_FOUND)
pkg_search_module(ENET QUIET IMPORTED_TARGET libenet)
endif()
pkg_search_module(ENET QUIET IMPORTED_TARGET libenet)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(enet
@@ -5,13 +5,11 @@
include(FindPackageHandleStandardArgs)
find_package(httplib QUIET CONFIG)
if (httplib_FOUND)
if (httplib_CONSIDERED_CONFIGS)
find_package_handle_standard_args(httplib CONFIG_MODE)
else()
find_package(PkgConfig QUIET)
if (PKG_CONFIG_FOUND)
pkg_search_module(HTTPLIB QUIET IMPORTED_TARGET cpp-httplib)
endif()
pkg_search_module(HTTPLIB QUIET IMPORTED_TARGET cpp-httplib)
find_package_handle_standard_args(httplib
REQUIRED_VARS HTTPLIB_INCLUDEDIR
VERSION_VAR HTTPLIB_VERSION
@@ -3,9 +3,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
find_package(PkgConfig QUIET)
if (PKG_CONFIG_FOUND)
pkg_search_module(INIREADER QUIET IMPORTED_TARGET INIReader)
endif()
pkg_search_module(INIREADER QUIET IMPORTED_TARGET INIReader)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(inih
@@ -3,9 +3,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
find_package(PkgConfig QUIET)
if (PKG_CONFIG_FOUND)
pkg_search_module(LIBUSB QUIET IMPORTED_TARGET libusb-1.0)
endif()
pkg_search_module(LIBUSB QUIET IMPORTED_TARGET libusb-1.0)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(libusb
@@ -4,13 +4,11 @@
include(FindPackageHandleStandardArgs)
find_package(lz4 QUIET CONFIG)
if (lz4_FOUND)
if (lz4_CONSIDERED_CONFIGS)
find_package_handle_standard_args(lz4 CONFIG_MODE)
else()
find_package(PkgConfig QUIET)
if (PKG_CONFIG_FOUND)
pkg_search_module(LZ4 QUIET IMPORTED_TARGET liblz4)
endif()
pkg_search_module(LZ4 QUIET IMPORTED_TARGET liblz4)
find_package_handle_standard_args(lz4
REQUIRED_VARS LZ4_LINK_LIBRARIES
VERSION_VAR LZ4_VERSION
@@ -4,13 +4,11 @@
include(FindPackageHandleStandardArgs)
find_package(zstd QUIET CONFIG)
if (zstd_FOUND)
if (zstd_CONSIDERED_CONFIGS)
find_package_handle_standard_args(zstd CONFIG_MODE)
else()
find_package(PkgConfig QUIET)
if (PKG_CONFIG_FOUND)
pkg_search_module(ZSTD QUIET IMPORTED_TARGET libzstd)
endif()
pkg_search_module(ZSTD QUIET IMPORTED_TARGET libzstd)
find_package_handle_standard_args(zstd
REQUIRED_VARS ZSTD_LINK_LIBRARIES
VERSION_VAR ZSTD_VERSION
+734 -600
View File
File diff suppressed because it is too large Load Diff
+734 -600
View File
File diff suppressed because it is too large Load Diff
+733 -599
View File
File diff suppressed because it is too large Load Diff
+757 -623
View File
File diff suppressed because it is too large Load Diff
+733 -599
View File
File diff suppressed because it is too large Load Diff
+736 -602
View File
File diff suppressed because it is too large Load Diff
+740 -603
View File
File diff suppressed because it is too large Load Diff
+733 -599
View File
File diff suppressed because it is too large Load Diff
+782 -649
View File
File diff suppressed because it is too large Load Diff
+734 -600
View File
File diff suppressed because it is too large Load Diff
+734 -600
View File
File diff suppressed because it is too large Load Diff
+734 -600
View File
File diff suppressed because it is too large Load Diff
+734 -600
View File
File diff suppressed because it is too large Load Diff
+734 -601
View File
File diff suppressed because it is too large Load Diff
+759 -625
View File
File diff suppressed because it is too large Load Diff
+741 -607
View File
File diff suppressed because it is too large Load Diff
+819 -682
View File
File diff suppressed because it is too large Load Diff
+734 -600
View File
File diff suppressed because it is too large Load Diff
+742 -604
View File
File diff suppressed because it is too large Load Diff
+806 -669
View File
File diff suppressed because it is too large Load Diff
+733 -599
View File
File diff suppressed because it is too large Load Diff
+733 -599
View File
File diff suppressed because it is too large Load Diff
+737 -600
View File
File diff suppressed because it is too large Load Diff
+739 -602
View File
File diff suppressed because it is too large Load Diff
+11 -12
View File
@@ -1,9 +1,9 @@
# SPDX-FileCopyrightText: 2016 Citra Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/CMakeModules")
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/externals/find-modules")
include(DownloadExternals)
# Dynarmic has cmake_minimum_required(3.12) and we may want to override
# some of its variables, which is only possible in 3.13+
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
# xbyak
if ((ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) AND NOT TARGET xbyak::xbyak)
@@ -12,8 +12,7 @@ endif()
# Dynarmic
if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) AND NOT TARGET dynarmic::dynarmic)
set(DYNARMIC_NO_BUNDLED_FMT ON)
set(DYNARMIC_IGNORE_ASSERTS ON CACHE BOOL "" FORCE)
set(DYNARMIC_IGNORE_ASSERTS ON)
add_subdirectory(dynarmic EXCLUDE_FROM_ALL)
add_library(dynarmic::dynarmic ALIAS dynarmic)
endif()
@@ -45,7 +44,7 @@ if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "12" AND CMAKE_CXX_COMPILER
endif()
# libusb
if (NOT TARGET libusb::usb)
if (ENABLE_LIBUSB AND NOT TARGET libusb::usb)
add_subdirectory(libusb EXCLUDE_FROM_ALL)
endif()
@@ -60,10 +59,10 @@ if (YUZU_USE_EXTERNAL_SDL2)
Locale Power Render)
foreach(_SUB ${SDL_UNUSED_SUBSYSTEMS})
string(TOUPPER ${_SUB} _OPT)
option(SDL_${_OPT} "" OFF)
set(SDL_${_OPT} OFF)
endforeach()
option(HIDAPI "" ON)
set(HIDAPI ON)
endif()
set(SDL_STATIC ON)
set(SDL_SHARED OFF)
@@ -83,7 +82,7 @@ endif()
# Cubeb
if (ENABLE_CUBEB AND NOT TARGET cubeb::cubeb)
set(BUILD_TESTS OFF CACHE BOOL "")
set(BUILD_TESTS OFF)
add_subdirectory(cubeb EXCLUDE_FROM_ALL)
add_library(cubeb::cubeb ALIAS cubeb)
endif()
@@ -98,6 +97,7 @@ endif()
# Sirit
add_subdirectory(sirit EXCLUDE_FROM_ALL)
# httplib
if (ENABLE_WEB_SERVICE AND NOT TARGET httplib::httplib)
if (NOT WIN32)
find_package(OpenSSL 1.1)
@@ -108,7 +108,7 @@ if (ENABLE_WEB_SERVICE AND NOT TARGET httplib::httplib)
if (WIN32 OR NOT OPENSSL_FOUND)
# LibreSSL
set(LIBRESSL_SKIP_INSTALL ON CACHE BOOL "")
set(LIBRESSL_SKIP_INSTALL ON)
set(OPENSSLDIR "/etc/ssl/")
add_subdirectory(libressl EXCLUDE_FROM_ALL)
target_include_directories(ssl INTERFACE ./libressl/include)
@@ -118,7 +118,6 @@ if (ENABLE_WEB_SERVICE AND NOT TARGET httplib::httplib)
DEFINITION OPENSSL_LIBS)
endif()
# httplib
add_library(httplib INTERFACE)
target_include_directories(httplib INTERFACE ./cpp-httplib)
target_compile_definitions(httplib INTERFACE -DCPPHTTPLIB_OPENSSL_SUPPORT)
@@ -152,6 +151,6 @@ if (YUZU_USE_BUNDLED_FFMPEG)
endif()
# Vulkan-Headers
if (NOT TARGET Vulkan::Headers)
if (YUZU_USE_EXTERNAL_VULKAN_HEADERS)
add_subdirectory(Vulkan-Headers EXCLUDE_FROM_ALL)
endif()
+4 -1
View File
@@ -161,7 +161,10 @@ add_subdirectory(video_core)
add_subdirectory(network)
add_subdirectory(input_common)
add_subdirectory(shader_recompiler)
add_subdirectory(dedicated_room)
if (YUZU_ROOM)
add_subdirectory(dedicated_room)
endif()
if (YUZU_TESTS)
add_subdirectory(tests)
+13 -6
View File
@@ -187,11 +187,7 @@ add_library(audio_core STATIC
renderer/voice/voice_info.cpp
renderer/voice/voice_info.h
renderer/voice/voice_state.h
sink/cubeb_sink.cpp
sink/cubeb_sink.h
sink/null_sink.h
sink/sdl2_sink.cpp
sink/sdl2_sink.h
sink/sink.h
sink/sink_details.cpp
sink/sink_details.h
@@ -222,11 +218,22 @@ if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
target_link_libraries(audio_core PRIVATE dynarmic::dynarmic)
endif()
if(ENABLE_CUBEB)
if (ENABLE_CUBEB)
target_sources(audio_core PRIVATE
sink/cubeb_sink.cpp
sink/cubeb_sink.h
)
target_link_libraries(audio_core PRIVATE cubeb::cubeb)
target_compile_definitions(audio_core PRIVATE -DHAVE_CUBEB=1)
endif()
if(ENABLE_SDL2)
if (ENABLE_SDL2)
target_sources(audio_core PRIVATE
sink/sdl2_sink.cpp
sink/sdl2_sink.h
)
target_link_libraries(audio_core PRIVATE SDL2::SDL2)
target_compile_definitions(audio_core PRIVATE HAVE_SDL2)
endif()
+5 -3
View File
@@ -91,9 +91,10 @@ public:
* @param core_timing - The CoreTiming instance
* @param session - The device session
*
* @return Is the buffer was released.
* @return If any buffer was released.
*/
bool ReleaseBuffers(const Core::Timing::CoreTiming& core_timing, const DeviceSession& session) {
bool ReleaseBuffers(const Core::Timing::CoreTiming& core_timing, const DeviceSession& session,
bool force) {
std::scoped_lock l{lock};
bool buffer_released{false};
while (registered_count > 0) {
@@ -103,7 +104,8 @@ public:
}
// Check with the backend if this buffer can be released yet.
if (!session.IsBufferConsumed(buffers[index])) {
// If we're shutting down, we don't care if it's been played or not.
if (!force && !session.IsBufferConsumed(buffers[index])) {
break;
}
+6
View File
@@ -73,6 +73,12 @@ void DeviceSession::Stop() {
}
}
void DeviceSession::ClearBuffers() {
if (stream) {
stream->ClearQueue();
}
}
void DeviceSession::AppendBuffers(std::span<const AudioBuffer> buffers) const {
for (const auto& buffer : buffers) {
Sink::SinkBuffer new_buffer{
+5
View File
@@ -90,6 +90,11 @@ public:
*/
void Stop();
/**
* Clear out the underlying audio buffers in the backend stream.
*/
void ClearBuffers();
/**
* Set this device session's volume.
*
+5 -2
View File
@@ -23,7 +23,6 @@ System::~System() {
void System::Finalize() {
Stop();
session->Finalize();
buffer_event->Signal();
}
void System::StartSession() {
@@ -102,6 +101,10 @@ Result System::Stop() {
if (state == State::Started) {
session->Stop();
session->SetVolume(0.0f);
session->ClearBuffers();
if (buffers.ReleaseBuffers(system.CoreTiming(), *session, true)) {
buffer_event->Signal();
}
state = State::Stopped;
}
@@ -138,7 +141,7 @@ void System::RegisterBuffers() {
}
void System::ReleaseBuffers() {
bool signal{buffers.ReleaseBuffers(system.CoreTiming(), *session)};
bool signal{buffers.ReleaseBuffers(system.CoreTiming(), *session, false)};
if (signal) {
// Signal if any buffer was released, or if none are registered, we need more.
+5 -2
View File
@@ -24,7 +24,6 @@ System::~System() {
void System::Finalize() {
Stop();
session->Finalize();
buffer_event->Signal();
}
std::string_view System::GetDefaultOutputDeviceName() const {
@@ -102,6 +101,10 @@ Result System::Stop() {
if (state == State::Started) {
session->Stop();
session->SetVolume(0.0f);
session->ClearBuffers();
if (buffers.ReleaseBuffers(system.CoreTiming(), *session, true)) {
buffer_event->Signal();
}
state = State::Stopped;
}
@@ -138,7 +141,7 @@ void System::RegisterBuffers() {
}
void System::ReleaseBuffers() {
bool signal{buffers.ReleaseBuffers(system.CoreTiming(), *session)};
bool signal{buffers.ReleaseBuffers(system.CoreTiming(), *session, false)};
if (signal) {
// Signal if any buffer was released, or if none are registered, we need more.
buffer_event->Signal();
+3
View File
@@ -78,6 +78,7 @@ add_library(common STATIC
logging/types.h
lz4_compression.cpp
lz4_compression.h
make_unique_for_overwrite.h
math_util.h
memory_detect.cpp
memory_detect.h
@@ -96,11 +97,13 @@ add_library(common STATIC
point.h
precompiled_headers.h
quaternion.h
range_map.h
reader_writer_queue.h
ring_buffer.h
${CMAKE_CURRENT_BINARY_DIR}/scm_rev.cpp
scm_rev.h
scope_exit.h
scratch_buffer.h
settings.cpp
settings.h
settings_input.cpp
+2 -2
View File
@@ -69,7 +69,7 @@ void assert_fail_impl();
#define ASSERT_OR_EXECUTE(_a_, _b_) \
do { \
ASSERT(_a_); \
if (!(_a_)) { \
if (!(_a_)) [[unlikely]] { \
_b_ \
} \
} while (0)
@@ -78,7 +78,7 @@ void assert_fail_impl();
#define ASSERT_OR_EXECUTE_MSG(_a_, _b_, ...) \
do { \
ASSERT_MSG(_a_, __VA_ARGS__); \
if (!(_a_)) { \
if (!(_a_)) [[unlikely]] { \
_b_ \
} \
} while (0)
+17 -2
View File
@@ -393,12 +393,27 @@ public:
}
// Virtual memory initialization
virtual_base = static_cast<u8*>(
mmap(nullptr, virtual_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
#if defined(__FreeBSD__)
virtual_base =
static_cast<u8*>(mmap(nullptr, virtual_size, PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_ALIGNED_SUPER, -1, 0));
if (virtual_base == MAP_FAILED) {
virtual_base = static_cast<u8*>(
mmap(nullptr, virtual_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
if (virtual_base == MAP_FAILED) {
LOG_CRITICAL(HW_Memory, "mmap failed: {}", strerror(errno));
throw std::bad_alloc{};
}
}
#else
virtual_base = static_cast<u8*>(mmap(nullptr, virtual_size, PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0));
if (virtual_base == MAP_FAILED) {
LOG_CRITICAL(HW_Memory, "mmap failed: {}", strerror(errno));
throw std::bad_alloc{};
}
madvise(virtual_base, virtual_size, MADV_HUGEPAGE);
#endif
good = true;
}
-3
View File
@@ -292,9 +292,6 @@ class InputDevice {
public:
virtual ~InputDevice() = default;
// Request input device to update if necessary
virtual void SoftUpdate() {}
// Force input device to update data regardless of the current state
virtual void ForceUpdate() {}
+25
View File
@@ -0,0 +1,25 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <memory>
#include <type_traits>
namespace Common {
template <class T>
requires(!std::is_array_v<T>) std::unique_ptr<T> make_unique_for_overwrite() {
return std::unique_ptr<T>(new T);
}
template <class T>
requires std::is_unbounded_array_v<T> std::unique_ptr<T> make_unique_for_overwrite(std::size_t n) {
return std::unique_ptr<T>(new std::remove_extent_t<T>[n]);
}
template <class T, class... Args>
requires std::is_bounded_array_v<T>
void make_unique_for_overwrite(Args&&...) = delete;
} // namespace Common
+139
View File
@@ -0,0 +1,139 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <map>
#include <type_traits>
#include "common/common_types.h"
namespace Common {
template <typename KeyTBase, typename ValueT>
class RangeMap {
private:
using KeyT =
std::conditional_t<std::is_signed_v<KeyTBase>, KeyTBase, std::make_signed_t<KeyTBase>>;
public:
explicit RangeMap(ValueT null_value_) : null_value{null_value_} {
container.emplace(std::numeric_limits<KeyT>::min(), null_value);
};
~RangeMap() = default;
void Map(KeyTBase address, KeyTBase address_end, ValueT value) {
KeyT new_address = static_cast<KeyT>(address);
KeyT new_address_end = static_cast<KeyT>(address_end);
if (new_address < 0) {
new_address = 0;
}
if (new_address_end < 0) {
new_address_end = 0;
}
InternalMap(new_address, new_address_end, value);
}
void Unmap(KeyTBase address, KeyTBase address_end) {
Map(address, address_end, null_value);
}
[[nodiscard]] size_t GetContinousSizeFrom(KeyTBase address) const {
const KeyT new_address = static_cast<KeyT>(address);
if (new_address < 0) {
return 0;
}
return ContinousSizeInternal(new_address);
}
[[nodiscard]] ValueT GetValueAt(KeyT address) const {
const KeyT new_address = static_cast<KeyT>(address);
if (new_address < 0) {
return null_value;
}
return GetValueInternal(new_address);
}
private:
using MapType = std::map<KeyT, ValueT>;
using IteratorType = typename MapType::iterator;
using ConstIteratorType = typename MapType::const_iterator;
size_t ContinousSizeInternal(KeyT address) const {
const auto it = GetFirstElementBeforeOrOn(address);
if (it == container.end() || it->second == null_value) {
return 0;
}
const auto it_end = std::next(it);
if (it_end == container.end()) {
return std::numeric_limits<KeyT>::max() - address;
}
return it_end->first - address;
}
ValueT GetValueInternal(KeyT address) const {
const auto it = GetFirstElementBeforeOrOn(address);
if (it == container.end()) {
return null_value;
}
return it->second;
}
ConstIteratorType GetFirstElementBeforeOrOn(KeyT address) const {
auto it = container.lower_bound(address);
if (it == container.begin()) {
return it;
}
if (it != container.end() && (it->first == address)) {
return it;
}
--it;
return it;
}
ValueT GetFirstValueWithin(KeyT address) {
auto it = container.lower_bound(address);
if (it == container.begin()) {
return it->second;
}
if (it == container.end()) [[unlikely]] { // this would be a bug
return null_value;
}
--it;
return it->second;
}
ValueT GetLastValueWithin(KeyT address) {
auto it = container.upper_bound(address);
if (it == container.end()) {
return null_value;
}
if (it == container.begin()) [[unlikely]] { // this would be a bug
return it->second;
}
--it;
return it->second;
}
void InternalMap(KeyT address, KeyT address_end, ValueT value) {
const bool must_add_start = GetFirstValueWithin(address) != value;
const ValueT last_value = GetLastValueWithin(address_end);
const bool must_add_end = last_value != value;
auto it = container.lower_bound(address);
const auto it_end = container.upper_bound(address_end);
while (it != it_end) {
it = container.erase(it);
}
if (must_add_start) {
container.emplace(address, value);
}
if (must_add_end) {
container.emplace(address_end, last_value);
}
}
ValueT null_value;
MapType container;
};
} // namespace Common
+95
View File
@@ -0,0 +1,95 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/make_unique_for_overwrite.h"
namespace Common {
/**
* ScratchBuffer class
* This class creates a default initialized heap allocated buffer for cases such as intermediate
* buffers being copied into entirely, where value initializing members during allocation or resize
* is redundant.
*/
template <typename T>
class ScratchBuffer {
public:
ScratchBuffer() = default;
explicit ScratchBuffer(size_t initial_capacity)
: last_requested_size{initial_capacity}, buffer_capacity{initial_capacity},
buffer{Common::make_unique_for_overwrite<T[]>(initial_capacity)} {}
~ScratchBuffer() = default;
/// This will only grow the buffer's capacity if size is greater than the current capacity.
/// The previously held data will remain intact.
void resize(size_t size) {
if (size > buffer_capacity) {
auto new_buffer = Common::make_unique_for_overwrite<T[]>(size);
std::move(buffer.get(), buffer.get() + buffer_capacity, new_buffer.get());
buffer = std::move(new_buffer);
buffer_capacity = size;
}
last_requested_size = size;
}
/// This will only grow the buffer's capacity if size is greater than the current capacity.
/// The previously held data will be destroyed if a reallocation occurs.
void resize_destructive(size_t size) {
if (size > buffer_capacity) {
buffer_capacity = size;
buffer = Common::make_unique_for_overwrite<T[]>(buffer_capacity);
}
last_requested_size = size;
}
[[nodiscard]] T* data() noexcept {
return buffer.get();
}
[[nodiscard]] const T* data() const noexcept {
return buffer.get();
}
[[nodiscard]] T* begin() noexcept {
return data();
}
[[nodiscard]] const T* begin() const noexcept {
return data();
}
[[nodiscard]] T* end() noexcept {
return data() + last_requested_size;
}
[[nodiscard]] const T* end() const noexcept {
return data() + last_requested_size;
}
[[nodiscard]] T& operator[](size_t i) {
return buffer[i];
}
[[nodiscard]] const T& operator[](size_t i) const {
return buffer[i];
}
[[nodiscard]] size_t size() const noexcept {
return last_requested_size;
}
[[nodiscard]] size_t capacity() const noexcept {
return buffer_capacity;
}
private:
size_t last_requested_size{};
size_t buffer_capacity{};
std::unique_ptr<T[]> buffer{};
};
} // namespace Common
+3
View File
@@ -40,6 +40,7 @@ void LogSettings() {
LOG_INFO(Config, "yuzu Configuration:");
log_setting("Controls_UseDockedMode", values.use_docked_mode.GetValue());
log_setting("System_RngSeed", values.rng_seed.GetValue().value_or(0));
log_setting("System_DeviceName", values.device_name.GetValue());
log_setting("System_CurrentUser", values.current_user.GetValue());
log_setting("System_LanguageIndex", values.language_index.GetValue());
log_setting("System_RegionIndex", values.region_index.GetValue());
@@ -184,6 +185,7 @@ void RestoreGlobalState(bool is_powered_on) {
// Renderer
values.fsr_sharpening_slider.SetGlobal(true);
values.renderer_backend.SetGlobal(true);
values.renderer_force_max_clock.SetGlobal(true);
values.vulkan_device.SetGlobal(true);
values.aspect_ratio.SetGlobal(true);
values.max_anisotropy.SetGlobal(true);
@@ -199,6 +201,7 @@ void RestoreGlobalState(bool is_powered_on) {
values.use_asynchronous_shaders.SetGlobal(true);
values.use_fast_gpu_time.SetGlobal(true);
values.use_pessimistic_flushes.SetGlobal(true);
values.use_vulkan_driver_pipeline_cache.SetGlobal(true);
values.bg_red.SetGlobal(true);
values.bg_green.SetGlobal(true);
values.bg_blue.SetGlobal(true);
+5
View File
@@ -415,6 +415,7 @@ struct Values {
// Renderer
SwitchableSetting<RendererBackend, true> renderer_backend{
RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Null, "backend"};
SwitchableSetting<bool> renderer_force_max_clock{false, "force_max_clock"};
Setting<bool> renderer_debug{false, "debug"};
Setting<bool> renderer_shader_feedback{false, "shader_feedback"};
Setting<bool> enable_nsight_aftermath{false, "nsight_aftermath"};
@@ -451,6 +452,8 @@ struct Values {
SwitchableSetting<bool> use_asynchronous_shaders{false, "use_asynchronous_shaders"};
SwitchableSetting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"};
SwitchableSetting<bool> use_pessimistic_flushes{false, "use_pessimistic_flushes"};
SwitchableSetting<bool> use_vulkan_driver_pipeline_cache{true,
"use_vulkan_driver_pipeline_cache"};
SwitchableSetting<u8> bg_red{0, "bg_red"};
SwitchableSetting<u8> bg_green{0, "bg_green"};
@@ -458,6 +461,7 @@ struct Values {
// System
SwitchableSetting<std::optional<u32>> rng_seed{std::optional<u32>(), "rng_seed"};
Setting<std::string> device_name{"Yuzu", "device_name"};
// Measured in seconds since epoch
std::optional<s64> custom_rtc;
// Set on game boot, reset on stop. Seconds difference between current time and `custom_rtc`
@@ -530,6 +534,7 @@ struct Values {
Setting<bool> reporting_services{false, "reporting_services"};
Setting<bool> quest_flag{false, "quest_flag"};
Setting<bool> disable_macro_jit{false, "disable_macro_jit"};
Setting<bool> disable_macro_hle{false, "disable_macro_hle"};
Setting<bool> extended_logging{false, "extended_logging"};
Setting<bool> use_debug_asserts{false, "use_debug_asserts"};
Setting<bool> use_auto_stub{false, "use_auto_stub"};
+5 -2
View File
@@ -201,6 +201,9 @@ add_library(core STATIC
hle/kernel/k_event_info.h
hle/kernel/k_handle_table.cpp
hle/kernel/k_handle_table.h
hle/kernel/k_hardware_timer_base.h
hle/kernel/k_hardware_timer.cpp
hle/kernel/k_hardware_timer.h
hle/kernel/k_interrupt_manager.cpp
hle/kernel/k_interrupt_manager.h
hle/kernel/k_light_condition_variable.cpp
@@ -223,6 +226,7 @@ add_library(core STATIC
hle/kernel/k_page_buffer.h
hle/kernel/k_page_heap.cpp
hle/kernel/k_page_heap.h
hle/kernel/k_page_group.cpp
hle/kernel/k_page_group.h
hle/kernel/k_page_table.cpp
hle/kernel/k_page_table.h
@@ -268,6 +272,7 @@ add_library(core STATIC
hle/kernel/k_thread_local_page.h
hle/kernel/k_thread_queue.cpp
hle/kernel/k_thread_queue.h
hle/kernel/k_timer_task.h
hle/kernel/k_trace.h
hle/kernel/k_transfer_memory.cpp
hle/kernel/k_transfer_memory.h
@@ -290,8 +295,6 @@ add_library(core STATIC
hle/kernel/svc_common.h
hle/kernel/svc_types.h
hle/kernel/svc_wrap.h
hle/kernel/time_manager.cpp
hle/kernel/time_manager.h
hle/result.h
hle/service/acc/acc.cpp
hle/service/acc/acc.h
@@ -229,7 +229,11 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
config.enable_cycle_counting = true;
// Code cache size
#ifdef ARCHITECTURE_arm64
config.code_cache_size = 128_MiB;
#else
config.code_cache_size = 512_MiB;
#endif
// Allow memory fault handling to work
if (system.DebuggerEnabled()) {
@@ -288,7 +288,11 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
config.enable_cycle_counting = true;
// Code cache size
#ifdef ARCHITECTURE_arm64
config.code_cache_size = 128_MiB;
#else
config.code_cache_size = 512_MiB;
#endif
// Allow memory fault handling to work
if (system.DebuggerEnabled()) {
+6 -12
View File
@@ -183,26 +183,20 @@ struct System::Impl {
Initialize(system);
}
SystemResultStatus Run() {
void Run() {
std::unique_lock<std::mutex> lk(suspend_guard);
status = SystemResultStatus::Success;
kernel.Suspend(false);
core_timing.SyncPause(false);
is_paused.store(false, std::memory_order_relaxed);
return status;
}
SystemResultStatus Pause() {
void Pause() {
std::unique_lock<std::mutex> lk(suspend_guard);
status = SystemResultStatus::Success;
core_timing.SyncPause(true);
kernel.Suspend(true);
is_paused.store(true, std::memory_order_relaxed);
return status;
}
bool IsPaused() const {
@@ -553,12 +547,12 @@ void System::Initialize() {
impl->Initialize(*this);
}
SystemResultStatus System::Run() {
return impl->Run();
void System::Run() {
impl->Run();
}
SystemResultStatus System::Pause() {
return impl->Pause();
void System::Pause() {
impl->Pause();
}
bool System::IsPaused() const {
+2 -2
View File
@@ -152,13 +152,13 @@ public:
* Run the OS and Application
* This function will start emulation and run the relevant devices
*/
[[nodiscard]] SystemResultStatus Run();
void Run();
/**
* Pause the OS and Application
* This function will pause emulation and stop the relevant devices
*/
[[nodiscard]] SystemResultStatus Pause();
void Pause();
/// Check if the core is currently paused.
[[nodiscard]] bool IsPaused() const;
+3 -3
View File
@@ -194,9 +194,9 @@ std::size_t VfsFile::WriteBytes(const std::vector<u8>& data, std::size_t offset)
std::string VfsFile::GetFullPath() const {
if (GetContainingDirectory() == nullptr)
return "/" + GetName();
return '/' + GetName();
return GetContainingDirectory()->GetFullPath() + "/" + GetName();
return GetContainingDirectory()->GetFullPath() + '/' + GetName();
}
VirtualFile VfsDirectory::GetFileRelative(std::string_view path) const {
@@ -435,7 +435,7 @@ std::string VfsDirectory::GetFullPath() const {
if (IsRoot())
return GetName();
return GetParentDirectory()->GetFullPath() + "/" + GetName();
return GetParentDirectory()->GetFullPath() + '/' + GetName();
}
bool ReadOnlyVfsDirectory::IsWritable() const {
+6
View File
@@ -131,6 +131,10 @@ public:
return active_config;
}
bool StrictContextRequired() const {
return strict_context_required;
}
/**
* Requests the internal configuration to be replaced by the specified argument at some point in
* the future.
@@ -207,6 +211,8 @@ protected:
WindowSystemInfo window_info;
bool strict_context_required = false;
private:
/**
* Handler called when the minimal client area was requested to be changed via SetConfig.
+5
View File
@@ -40,6 +40,11 @@ void EmulatedConsole::SetTouchParams() {
touch_params[index++] = std::move(touchscreen_param);
}
if (Settings::values.touch_from_button_maps.empty()) {
LOG_WARNING(Input, "touch_from_button_maps is unset by frontend config");
return;
}
const auto button_index =
static_cast<u64>(Settings::values.touch_from_button_map_index.GetValue());
const auto& touch_buttons = Settings::values.touch_from_button_maps[button_index].buttons;
+96 -15
View File
@@ -11,6 +11,11 @@
namespace Core::HID {
constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
constexpr s32 HID_TRIGGER_MAX = 0x7fff;
// Use a common UUID for TAS and Virtual Gamepad
constexpr Common::UUID TAS_UUID =
Common::UUID{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xA5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
constexpr Common::UUID VIRTUAL_UUID =
Common::UUID{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
EmulatedController::EmulatedController(NpadIdType npad_id_type_) : npad_id_type(npad_id_type_) {}
@@ -145,6 +150,7 @@ void EmulatedController::LoadDevices() {
output_params[3].Set("output", true);
LoadTASParams();
LoadVirtualGamepadParams();
std::ranges::transform(button_params, button_devices.begin(), Common::Input::CreateInputDevice);
std::ranges::transform(stick_params, stick_devices.begin(), Common::Input::CreateInputDevice);
@@ -163,6 +169,12 @@ void EmulatedController::LoadDevices() {
Common::Input::CreateInputDevice);
std::ranges::transform(tas_stick_params, tas_stick_devices.begin(),
Common::Input::CreateInputDevice);
// Initialize virtual gamepad devices
std::ranges::transform(virtual_button_params, virtual_button_devices.begin(),
Common::Input::CreateInputDevice);
std::ranges::transform(virtual_stick_params, virtual_stick_devices.begin(),
Common::Input::CreateInputDevice);
}
void EmulatedController::LoadTASParams() {
@@ -203,6 +215,53 @@ void EmulatedController::LoadTASParams() {
tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1);
tas_stick_params[Settings::NativeAnalog::RStick].Set("axis_x", 2);
tas_stick_params[Settings::NativeAnalog::RStick].Set("axis_y", 3);
// set to optimal stick to avoid sanitizing the stick and tweaking the coordinates
// making sure they play back in the game as originally written down in the script file
tas_stick_params[Settings::NativeAnalog::LStick].Set("deadzone", 0.0f);
tas_stick_params[Settings::NativeAnalog::LStick].Set("range", 1.0f);
tas_stick_params[Settings::NativeAnalog::RStick].Set("deadzone", 0.0f);
tas_stick_params[Settings::NativeAnalog::RStick].Set("range", 1.0f);
}
void EmulatedController::LoadVirtualGamepadParams() {
const auto player_index = NpadIdTypeToIndex(npad_id_type);
Common::ParamPackage common_params{};
common_params.Set("engine", "virtual_gamepad");
common_params.Set("port", static_cast<int>(player_index));
for (auto& param : virtual_button_params) {
param = common_params;
}
for (auto& param : virtual_stick_params) {
param = common_params;
}
// TODO(german77): Replace this with an input profile or something better
virtual_button_params[Settings::NativeButton::A].Set("button", 0);
virtual_button_params[Settings::NativeButton::B].Set("button", 1);
virtual_button_params[Settings::NativeButton::X].Set("button", 2);
virtual_button_params[Settings::NativeButton::Y].Set("button", 3);
virtual_button_params[Settings::NativeButton::LStick].Set("button", 4);
virtual_button_params[Settings::NativeButton::RStick].Set("button", 5);
virtual_button_params[Settings::NativeButton::L].Set("button", 6);
virtual_button_params[Settings::NativeButton::R].Set("button", 7);
virtual_button_params[Settings::NativeButton::ZL].Set("button", 8);
virtual_button_params[Settings::NativeButton::ZR].Set("button", 9);
virtual_button_params[Settings::NativeButton::Plus].Set("button", 10);
virtual_button_params[Settings::NativeButton::Minus].Set("button", 11);
virtual_button_params[Settings::NativeButton::DLeft].Set("button", 12);
virtual_button_params[Settings::NativeButton::DUp].Set("button", 13);
virtual_button_params[Settings::NativeButton::DRight].Set("button", 14);
virtual_button_params[Settings::NativeButton::DDown].Set("button", 15);
virtual_button_params[Settings::NativeButton::SL].Set("button", 16);
virtual_button_params[Settings::NativeButton::SR].Set("button", 17);
virtual_button_params[Settings::NativeButton::Home].Set("button", 18);
virtual_button_params[Settings::NativeButton::Screenshot].Set("button", 19);
virtual_stick_params[Settings::NativeAnalog::LStick].Set("axis_x", 0);
virtual_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1);
virtual_stick_params[Settings::NativeAnalog::RStick].Set("axis_x", 2);
virtual_stick_params[Settings::NativeAnalog::RStick].Set("axis_y", 3);
}
void EmulatedController::ReloadInput() {
@@ -294,10 +353,6 @@ void EmulatedController::ReloadInput() {
}
}
// Use a common UUID for TAS
static constexpr Common::UUID TAS_UUID = Common::UUID{
{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xA5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
// Register TAS devices. No need to force update
for (std::size_t index = 0; index < tas_button_devices.size(); ++index) {
if (!tas_button_devices[index]) {
@@ -322,6 +377,31 @@ void EmulatedController::ReloadInput() {
},
});
}
// Register virtual devices. No need to force update
for (std::size_t index = 0; index < virtual_button_devices.size(); ++index) {
if (!virtual_button_devices[index]) {
continue;
}
virtual_button_devices[index]->SetCallback({
.on_change =
[this, index](const Common::Input::CallbackStatus& callback) {
SetButton(callback, index, VIRTUAL_UUID);
},
});
}
for (std::size_t index = 0; index < virtual_stick_devices.size(); ++index) {
if (!virtual_stick_devices[index]) {
continue;
}
virtual_stick_devices[index]->SetCallback({
.on_change =
[this, index](const Common::Input::CallbackStatus& callback) {
SetStick(callback, index, VIRTUAL_UUID);
},
});
}
}
void EmulatedController::UnloadInput() {
@@ -349,6 +429,12 @@ void EmulatedController::UnloadInput() {
for (auto& stick : tas_stick_devices) {
stick.reset();
}
for (auto& button : virtual_button_devices) {
button.reset();
}
for (auto& stick : virtual_stick_devices) {
stick.reset();
}
camera_devices.reset();
nfc_devices.reset();
}
@@ -691,7 +777,12 @@ void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback,
// Only read stick values that have the same uuid or are over the threshold to avoid flapping
if (controller.stick_values[index].uuid != uuid) {
if (!stick_value.down && !stick_value.up && !stick_value.left && !stick_value.right) {
const bool is_tas = uuid == TAS_UUID;
if (is_tas && stick_value.x.value == 0 && stick_value.y.value == 0) {
return;
}
if (!is_tas && !stick_value.down && !stick_value.up && !stick_value.left &&
!stick_value.right) {
return;
}
}
@@ -1343,16 +1434,6 @@ AnalogSticks EmulatedController::GetSticks() const {
return {};
}
// Some drivers like stick from buttons need constant refreshing
for (auto& device : stick_devices) {
if (!device) {
continue;
}
lock.unlock();
device->SoftUpdate();
lock.lock();
}
return controller.analog_stick_state;
}
+9
View File
@@ -385,6 +385,9 @@ private:
/// Set the params for TAS devices
void LoadTASParams();
/// Set the params for virtual pad devices
void LoadVirtualGamepadParams();
/**
* @param use_temporary_value If true tmp_npad_type will be used
* @return true if the controller style is fullkey
@@ -500,6 +503,12 @@ private:
ButtonDevices tas_button_devices;
StickDevices tas_stick_devices;
// Virtual gamepad related variables
ButtonParams virtual_button_params;
StickParams virtual_stick_params;
ButtonDevices virtual_button_devices;
StickDevices virtual_stick_devices;
mutable std::mutex mutex;
mutable std::mutex callback_mutex;
std::unordered_map<int, ControllerUpdateCallback> callback_list;
+14 -8
View File
@@ -167,6 +167,9 @@ void HLERequestContext::ParseCommandBuffer(const KHandleTable& handle_table, u32
}
if (incoming) {
// Populate the object lists with the data in the IPC request.
incoming_copy_handles.reserve(handle_descriptor_header->num_handles_to_copy);
incoming_move_handles.reserve(handle_descriptor_header->num_handles_to_move);
for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_copy; ++handle) {
incoming_copy_handles.push_back(rp.Pop<Handle>());
}
@@ -181,6 +184,11 @@ void HLERequestContext::ParseCommandBuffer(const KHandleTable& handle_table, u32
}
}
buffer_x_desciptors.reserve(command_header->num_buf_x_descriptors);
buffer_a_desciptors.reserve(command_header->num_buf_a_descriptors);
buffer_b_desciptors.reserve(command_header->num_buf_b_descriptors);
buffer_w_desciptors.reserve(command_header->num_buf_w_descriptors);
for (u32 i = 0; i < command_header->num_buf_x_descriptors; ++i) {
buffer_x_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorX>());
}
@@ -318,25 +326,23 @@ Result HLERequestContext::WriteToOutgoingCommandBuffer(KThread& requesting_threa
}
std::vector<u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) const {
std::vector<u8> buffer{};
const bool is_buffer_a{BufferDescriptorA().size() > buffer_index &&
BufferDescriptorA()[buffer_index].Size()};
if (is_buffer_a) {
ASSERT_OR_EXECUTE_MSG(
BufferDescriptorA().size() > buffer_index, { return buffer; },
BufferDescriptorA().size() > buffer_index, { return {}; },
"BufferDescriptorA invalid buffer_index {}", buffer_index);
buffer.resize(BufferDescriptorA()[buffer_index].Size());
std::vector<u8> buffer(BufferDescriptorA()[buffer_index].Size());
memory.ReadBlock(BufferDescriptorA()[buffer_index].Address(), buffer.data(), buffer.size());
return buffer;
} else {
ASSERT_OR_EXECUTE_MSG(
BufferDescriptorX().size() > buffer_index, { return buffer; },
BufferDescriptorX().size() > buffer_index, { return {}; },
"BufferDescriptorX invalid buffer_index {}", buffer_index);
buffer.resize(BufferDescriptorX()[buffer_index].Size());
std::vector<u8> buffer(BufferDescriptorX()[buffer_index].Size());
memory.ReadBlock(BufferDescriptorX()[buffer_index].Address(), buffer.data(), buffer.size());
return buffer;
}
return buffer;
}
std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size,
@@ -10,7 +10,6 @@
#include "core/hle/kernel/k_thread_queue.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/svc_results.h"
#include "core/hle/kernel/time_manager.h"
#include "core/memory.h"
namespace Kernel {
+15 -14
View File
@@ -27,13 +27,13 @@ Result KCodeMemory::Initialize(Core::DeviceMemory& device_memory, VAddr addr, si
auto& page_table = m_owner->PageTable();
// Construct the page group.
m_page_group = {};
m_page_group.emplace(kernel, page_table.GetBlockInfoManager());
// Lock the memory.
R_TRY(page_table.LockForCodeMemory(&m_page_group, addr, size))
R_TRY(page_table.LockForCodeMemory(std::addressof(*m_page_group), addr, size))
// Clear the memory.
for (const auto& block : m_page_group.Nodes()) {
for (const auto& block : *m_page_group) {
std::memset(device_memory.GetPointer<void>(block.GetAddress()), 0xFF, block.GetSize());
}
@@ -51,12 +51,13 @@ Result KCodeMemory::Initialize(Core::DeviceMemory& device_memory, VAddr addr, si
void KCodeMemory::Finalize() {
// Unlock.
if (!m_is_mapped && !m_is_owner_mapped) {
const size_t size = m_page_group.GetNumPages() * PageSize;
m_owner->PageTable().UnlockForCodeMemory(m_address, size, m_page_group);
const size_t size = m_page_group->GetNumPages() * PageSize;
m_owner->PageTable().UnlockForCodeMemory(m_address, size, *m_page_group);
}
// Close the page group.
m_page_group = {};
m_page_group->Close();
m_page_group->Finalize();
// Close our reference to our owner.
m_owner->Close();
@@ -64,7 +65,7 @@ void KCodeMemory::Finalize() {
Result KCodeMemory::Map(VAddr address, size_t size) {
// Validate the size.
R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize);
R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize);
// Lock ourselves.
KScopedLightLock lk(m_lock);
@@ -74,7 +75,7 @@ Result KCodeMemory::Map(VAddr address, size_t size) {
// Map the memory.
R_TRY(kernel.CurrentProcess()->PageTable().MapPages(
address, m_page_group, KMemoryState::CodeOut, KMemoryPermission::UserReadWrite));
address, *m_page_group, KMemoryState::CodeOut, KMemoryPermission::UserReadWrite));
// Mark ourselves as mapped.
m_is_mapped = true;
@@ -84,13 +85,13 @@ Result KCodeMemory::Map(VAddr address, size_t size) {
Result KCodeMemory::Unmap(VAddr address, size_t size) {
// Validate the size.
R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize);
R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize);
// Lock ourselves.
KScopedLightLock lk(m_lock);
// Unmap the memory.
R_TRY(kernel.CurrentProcess()->PageTable().UnmapPages(address, m_page_group,
R_TRY(kernel.CurrentProcess()->PageTable().UnmapPages(address, *m_page_group,
KMemoryState::CodeOut));
// Mark ourselves as unmapped.
@@ -101,7 +102,7 @@ Result KCodeMemory::Unmap(VAddr address, size_t size) {
Result KCodeMemory::MapToOwner(VAddr address, size_t size, Svc::MemoryPermission perm) {
// Validate the size.
R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize);
R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize);
// Lock ourselves.
KScopedLightLock lk(m_lock);
@@ -125,7 +126,7 @@ Result KCodeMemory::MapToOwner(VAddr address, size_t size, Svc::MemoryPermission
// Map the memory.
R_TRY(
m_owner->PageTable().MapPages(address, m_page_group, KMemoryState::GeneratedCode, k_perm));
m_owner->PageTable().MapPages(address, *m_page_group, KMemoryState::GeneratedCode, k_perm));
// Mark ourselves as mapped.
m_is_owner_mapped = true;
@@ -135,13 +136,13 @@ Result KCodeMemory::MapToOwner(VAddr address, size_t size, Svc::MemoryPermission
Result KCodeMemory::UnmapFromOwner(VAddr address, size_t size) {
// Validate the size.
R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize);
R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize);
// Lock ourselves.
KScopedLightLock lk(m_lock);
// Unmap the memory.
R_TRY(m_owner->PageTable().UnmapPages(address, m_page_group, KMemoryState::GeneratedCode));
R_TRY(m_owner->PageTable().UnmapPages(address, *m_page_group, KMemoryState::GeneratedCode));
// Mark ourselves as unmapped.
m_is_owner_mapped = false;
+4 -2
View File
@@ -3,6 +3,8 @@
#pragma once
#include <optional>
#include "common/common_types.h"
#include "core/device_memory.h"
#include "core/hle/kernel/k_auto_object.h"
@@ -49,11 +51,11 @@ public:
return m_address;
}
size_t GetSize() const {
return m_is_initialized ? m_page_group.GetNumPages() * PageSize : 0;
return m_is_initialized ? m_page_group->GetNumPages() * PageSize : 0;
}
private:
KPageGroup m_page_group{};
std::optional<KPageGroup> m_page_group{};
KProcess* m_owner{};
VAddr m_address{};
KLightLock m_lock;
+74
View File
@@ -0,0 +1,74 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/kernel/k_hardware_timer.h"
#include "core/hle/kernel/k_scheduler.h"
namespace Kernel {
void KHardwareTimer::Initialize() {
// Create the timing callback to register with CoreTiming.
m_event_type = Core::Timing::CreateEvent(
"KHardwareTimer::Callback", [](std::uintptr_t timer_handle, s64, std::chrono::nanoseconds) {
reinterpret_cast<KHardwareTimer*>(timer_handle)->DoTask();
return std::nullopt;
});
}
void KHardwareTimer::Finalize() {
this->DisableInterrupt();
m_event_type.reset();
}
void KHardwareTimer::DoTask() {
// Handle the interrupt.
{
KScopedSchedulerLock slk{m_kernel};
KScopedSpinLock lk(this->GetLock());
//! Ignore this event if needed.
if (!this->GetInterruptEnabled()) {
return;
}
// Disable the timer interrupt while we handle this.
this->DisableInterrupt();
if (const s64 next_time = this->DoInterruptTaskImpl(GetTick());
0 < next_time && next_time <= m_wakeup_time) {
// We have a next time, so we should set the time to interrupt and turn the interrupt
// on.
this->EnableInterrupt(next_time);
}
}
// Clear the timer interrupt.
// Kernel::GetInterruptManager().ClearInterrupt(KInterruptName_NonSecurePhysicalTimer,
// GetCurrentCoreId());
}
void KHardwareTimer::EnableInterrupt(s64 wakeup_time) {
this->DisableInterrupt();
m_wakeup_time = wakeup_time;
m_kernel.System().CoreTiming().ScheduleEvent(std::chrono::nanoseconds{m_wakeup_time},
m_event_type, reinterpret_cast<uintptr_t>(this),
true);
}
void KHardwareTimer::DisableInterrupt() {
m_kernel.System().CoreTiming().UnscheduleEvent(m_event_type, reinterpret_cast<uintptr_t>(this));
m_wakeup_time = std::numeric_limits<s64>::max();
}
s64 KHardwareTimer::GetTick() const {
return m_kernel.System().CoreTiming().GetGlobalTimeNs().count();
}
bool KHardwareTimer::GetInterruptEnabled() {
return m_wakeup_time != std::numeric_limits<s64>::max();
}
} // namespace Kernel
+54
View File
@@ -0,0 +1,54 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/kernel/k_hardware_timer_base.h"
namespace Core::Timing {
struct EventType;
} // namespace Core::Timing
namespace Kernel {
class KHardwareTimer : /* public KInterruptTask, */ public KHardwareTimerBase {
public:
explicit KHardwareTimer(KernelCore& kernel) : KHardwareTimerBase{kernel} {}
// Public API.
void Initialize();
void Finalize();
s64 GetCount() const {
return GetTick();
}
void RegisterTask(KTimerTask* task, s64 time_from_now) {
this->RegisterAbsoluteTask(task, GetTick() + time_from_now);
}
void RegisterAbsoluteTask(KTimerTask* task, s64 task_time) {
KScopedDisableDispatch dd{m_kernel};
KScopedSpinLock lk{this->GetLock()};
if (this->RegisterAbsoluteTaskImpl(task, task_time)) {
if (task_time <= m_wakeup_time) {
this->EnableInterrupt(task_time);
}
}
}
private:
void EnableInterrupt(s64 wakeup_time);
void DisableInterrupt();
bool GetInterruptEnabled();
s64 GetTick() const;
void DoTask();
private:
// Absolute time in nanoseconds
s64 m_wakeup_time{std::numeric_limits<s64>::max()};
std::shared_ptr<Core::Timing::EventType> m_event_type{};
};
} // namespace Kernel
@@ -0,0 +1,92 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/kernel/k_spin_lock.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/k_timer_task.h"
namespace Kernel {
class KHardwareTimerBase {
public:
explicit KHardwareTimerBase(KernelCore& kernel) : m_kernel{kernel} {}
void CancelTask(KTimerTask* task) {
KScopedDisableDispatch dd{m_kernel};
KScopedSpinLock lk{m_lock};
if (const s64 task_time = task->GetTime(); task_time > 0) {
this->RemoveTaskFromTree(task);
}
}
protected:
KSpinLock& GetLock() {
return m_lock;
}
s64 DoInterruptTaskImpl(s64 cur_time) {
// We want to handle all tasks, returning the next time that a task is scheduled.
while (true) {
// Get the next task. If there isn't one, return 0.
KTimerTask* task = m_next_task;
if (task == nullptr) {
return 0;
}
// If the task needs to be done in the future, do it in the future and not now.
if (const s64 task_time = task->GetTime(); task_time > cur_time) {
return task_time;
}
// Remove the task from the tree of tasks, and update our next task.
this->RemoveTaskFromTree(task);
// Handle the task.
task->OnTimer();
}
}
bool RegisterAbsoluteTaskImpl(KTimerTask* task, s64 task_time) {
ASSERT(task_time > 0);
// Set the task's time, and insert it into our tree.
task->SetTime(task_time);
m_task_tree.insert(*task);
// Update our next task if relevant.
if (m_next_task != nullptr && m_next_task->GetTime() <= task_time) {
return false;
}
m_next_task = task;
return true;
}
private:
void RemoveTaskFromTree(KTimerTask* task) {
// Erase from the tree.
auto it = m_task_tree.erase(m_task_tree.iterator_to(*task));
// Clear the task's scheduled time.
task->SetTime(0);
// Update our next task if relevant.
if (m_next_task == task) {
m_next_task = (it != m_task_tree.end()) ? std::addressof(*it) : nullptr;
}
}
protected:
KernelCore& m_kernel;
private:
using TimerTaskTree = Common::IntrusiveRedBlackTreeBaseTraits<KTimerTask>::TreeType<KTimerTask>;
KSpinLock m_lock{};
TimerTaskTree m_task_tree{};
KTimerTask* m_next_task{};
};
} // namespace Kernel
+4 -4
View File
@@ -223,7 +223,7 @@ Result KMemoryManager::AllocatePageGroupImpl(KPageGroup* out, size_t num_pages,
// Ensure that we don't leave anything un-freed.
ON_RESULT_FAILURE {
for (const auto& it : out->Nodes()) {
for (const auto& it : *out) {
auto& manager = this->GetManager(it.GetAddress());
const size_t node_num_pages = std::min<u64>(
it.GetNumPages(), (manager.GetEndAddress() - it.GetAddress()) / PageSize);
@@ -285,7 +285,7 @@ Result KMemoryManager::AllocateAndOpen(KPageGroup* out, size_t num_pages, u32 op
m_has_optimized_process[static_cast<size_t>(pool)], true));
// Open the first reference to the pages.
for (const auto& block : out->Nodes()) {
for (const auto& block : *out) {
PAddr cur_address = block.GetAddress();
size_t remaining_pages = block.GetNumPages();
while (remaining_pages > 0) {
@@ -335,7 +335,7 @@ Result KMemoryManager::AllocateForProcess(KPageGroup* out, size_t num_pages, u32
// Perform optimized memory tracking, if we should.
if (optimized) {
// Iterate over the allocated blocks.
for (const auto& block : out->Nodes()) {
for (const auto& block : *out) {
// Get the block extents.
const PAddr block_address = block.GetAddress();
const size_t block_pages = block.GetNumPages();
@@ -391,7 +391,7 @@ Result KMemoryManager::AllocateForProcess(KPageGroup* out, size_t num_pages, u32
}
} else {
// Set all the allocated memory.
for (const auto& block : out->Nodes()) {
for (const auto& block : *out) {
std::memset(m_system.DeviceMemory().GetPointer<void>(block.GetAddress()), fill_pattern,
block.GetSize());
}
+121
View File
@@ -0,0 +1,121 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/kernel/k_dynamic_resource_manager.h"
#include "core/hle/kernel/k_memory_manager.h"
#include "core/hle/kernel/k_page_group.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel {
void KPageGroup::Finalize() {
KBlockInfo* cur = m_first_block;
while (cur != nullptr) {
KBlockInfo* next = cur->GetNext();
m_manager->Free(cur);
cur = next;
}
m_first_block = nullptr;
m_last_block = nullptr;
}
void KPageGroup::CloseAndReset() {
auto& mm = m_kernel.MemoryManager();
KBlockInfo* cur = m_first_block;
while (cur != nullptr) {
KBlockInfo* next = cur->GetNext();
mm.Close(cur->GetAddress(), cur->GetNumPages());
m_manager->Free(cur);
cur = next;
}
m_first_block = nullptr;
m_last_block = nullptr;
}
size_t KPageGroup::GetNumPages() const {
size_t num_pages = 0;
for (const auto& it : *this) {
num_pages += it.GetNumPages();
}
return num_pages;
}
Result KPageGroup::AddBlock(KPhysicalAddress addr, size_t num_pages) {
// Succeed immediately if we're adding no pages.
R_SUCCEED_IF(num_pages == 0);
// Check for overflow.
ASSERT(addr < addr + num_pages * PageSize);
// Try to just append to the last block.
if (m_last_block != nullptr) {
R_SUCCEED_IF(m_last_block->TryConcatenate(addr, num_pages));
}
// Allocate a new block.
KBlockInfo* new_block = m_manager->Allocate();
R_UNLESS(new_block != nullptr, ResultOutOfResource);
// Initialize the block.
new_block->Initialize(addr, num_pages);
// Add the block to our list.
if (m_last_block != nullptr) {
m_last_block->SetNext(new_block);
} else {
m_first_block = new_block;
}
m_last_block = new_block;
R_SUCCEED();
}
void KPageGroup::Open() const {
auto& mm = m_kernel.MemoryManager();
for (const auto& it : *this) {
mm.Open(it.GetAddress(), it.GetNumPages());
}
}
void KPageGroup::OpenFirst() const {
auto& mm = m_kernel.MemoryManager();
for (const auto& it : *this) {
mm.OpenFirst(it.GetAddress(), it.GetNumPages());
}
}
void KPageGroup::Close() const {
auto& mm = m_kernel.MemoryManager();
for (const auto& it : *this) {
mm.Close(it.GetAddress(), it.GetNumPages());
}
}
bool KPageGroup::IsEquivalentTo(const KPageGroup& rhs) const {
auto lit = this->begin();
auto rit = rhs.begin();
auto lend = this->end();
auto rend = rhs.end();
while (lit != lend && rit != rend) {
if (*lit != *rit) {
return false;
}
++lit;
++rit;
}
return lit == lend && rit == rend;
}
} // namespace Kernel
+98 -77
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
@@ -13,24 +13,23 @@
namespace Kernel {
class KBlockInfoManager;
class KernelCore;
class KPageGroup;
class KBlockInfo {
private:
friend class KPageGroup;
public:
constexpr KBlockInfo() = default;
constexpr explicit KBlockInfo() : m_next(nullptr) {}
constexpr void Initialize(PAddr addr, size_t np) {
constexpr void Initialize(KPhysicalAddress addr, size_t np) {
ASSERT(Common::IsAligned(addr, PageSize));
ASSERT(static_cast<u32>(np) == np);
m_page_index = static_cast<u32>(addr) / PageSize;
m_page_index = static_cast<u32>(addr / PageSize);
m_num_pages = static_cast<u32>(np);
}
constexpr PAddr GetAddress() const {
constexpr KPhysicalAddress GetAddress() const {
return m_page_index * PageSize;
}
constexpr size_t GetNumPages() const {
@@ -39,10 +38,10 @@ public:
constexpr size_t GetSize() const {
return this->GetNumPages() * PageSize;
}
constexpr PAddr GetEndAddress() const {
constexpr KPhysicalAddress GetEndAddress() const {
return (m_page_index + m_num_pages) * PageSize;
}
constexpr PAddr GetLastAddress() const {
constexpr KPhysicalAddress GetLastAddress() const {
return this->GetEndAddress() - 1;
}
@@ -62,8 +61,8 @@ public:
return !(*this == rhs);
}
constexpr bool IsStrictlyBefore(PAddr addr) const {
const PAddr end = this->GetEndAddress();
constexpr bool IsStrictlyBefore(KPhysicalAddress addr) const {
const KPhysicalAddress end = this->GetEndAddress();
if (m_page_index != 0 && end == 0) {
return false;
@@ -72,11 +71,11 @@ public:
return end < addr;
}
constexpr bool operator<(PAddr addr) const {
constexpr bool operator<(KPhysicalAddress addr) const {
return this->IsStrictlyBefore(addr);
}
constexpr bool TryConcatenate(PAddr addr, size_t np) {
constexpr bool TryConcatenate(KPhysicalAddress addr, size_t np) {
if (addr != 0 && addr == this->GetEndAddress()) {
m_num_pages += static_cast<u32>(np);
return true;
@@ -90,96 +89,118 @@ private:
}
private:
friend class KPageGroup;
KBlockInfo* m_next{};
u32 m_page_index{};
u32 m_num_pages{};
};
static_assert(sizeof(KBlockInfo) <= 0x10);
class KPageGroup final {
class KPageGroup {
public:
class Node final {
class Iterator {
public:
constexpr Node(u64 addr_, std::size_t num_pages_) : addr{addr_}, num_pages{num_pages_} {}
using iterator_category = std::forward_iterator_tag;
using value_type = const KBlockInfo;
using difference_type = std::ptrdiff_t;
using pointer = value_type*;
using reference = value_type&;
constexpr u64 GetAddress() const {
return addr;
constexpr explicit Iterator(pointer n) : m_node(n) {}
constexpr bool operator==(const Iterator& rhs) const {
return m_node == rhs.m_node;
}
constexpr bool operator!=(const Iterator& rhs) const {
return !(*this == rhs);
}
constexpr std::size_t GetNumPages() const {
return num_pages;
constexpr pointer operator->() const {
return m_node;
}
constexpr reference operator*() const {
return *m_node;
}
constexpr std::size_t GetSize() const {
return GetNumPages() * PageSize;
constexpr Iterator& operator++() {
m_node = m_node->GetNext();
return *this;
}
constexpr Iterator operator++(int) {
const Iterator it{*this};
++(*this);
return it;
}
private:
u64 addr{};
std::size_t num_pages{};
pointer m_node{};
};
public:
KPageGroup() = default;
KPageGroup(u64 address, u64 num_pages) {
ASSERT(AddBlock(address, num_pages).IsSuccess());
explicit KPageGroup(KernelCore& kernel, KBlockInfoManager* m)
: m_kernel{kernel}, m_manager{m} {}
~KPageGroup() {
this->Finalize();
}
constexpr std::list<Node>& Nodes() {
return nodes;
void CloseAndReset();
void Finalize();
Iterator begin() const {
return Iterator{m_first_block};
}
Iterator end() const {
return Iterator{nullptr};
}
bool empty() const {
return m_first_block == nullptr;
}
constexpr const std::list<Node>& Nodes() const {
return nodes;
Result AddBlock(KPhysicalAddress addr, size_t num_pages);
void Open() const;
void OpenFirst() const;
void Close() const;
size_t GetNumPages() const;
bool IsEquivalentTo(const KPageGroup& rhs) const;
bool operator==(const KPageGroup& rhs) const {
return this->IsEquivalentTo(rhs);
}
std::size_t GetNumPages() const {
std::size_t num_pages = 0;
for (const Node& node : nodes) {
num_pages += node.GetNumPages();
}
return num_pages;
bool operator!=(const KPageGroup& rhs) const {
return !(*this == rhs);
}
bool IsEqual(KPageGroup& other) const {
auto this_node = nodes.begin();
auto other_node = other.nodes.begin();
while (this_node != nodes.end() && other_node != other.nodes.end()) {
if (this_node->GetAddress() != other_node->GetAddress() ||
this_node->GetNumPages() != other_node->GetNumPages()) {
return false;
}
this_node = std::next(this_node);
other_node = std::next(other_node);
}
return this_node == nodes.end() && other_node == other.nodes.end();
}
Result AddBlock(u64 address, u64 num_pages) {
if (!num_pages) {
return ResultSuccess;
}
if (!nodes.empty()) {
const auto node = nodes.back();
if (node.GetAddress() + node.GetNumPages() * PageSize == address) {
address = node.GetAddress();
num_pages += node.GetNumPages();
nodes.pop_back();
}
}
nodes.push_back({address, num_pages});
return ResultSuccess;
}
bool Empty() const {
return nodes.empty();
}
void Finalize() {}
private:
std::list<Node> nodes;
KernelCore& m_kernel;
KBlockInfo* m_first_block{};
KBlockInfo* m_last_block{};
KBlockInfoManager* m_manager{};
};
class KScopedPageGroup {
public:
explicit KScopedPageGroup(const KPageGroup* gp) : m_pg(gp) {
if (m_pg) {
m_pg->Open();
}
}
explicit KScopedPageGroup(const KPageGroup& gp) : KScopedPageGroup(std::addressof(gp)) {}
~KScopedPageGroup() {
if (m_pg) {
m_pg->Close();
}
}
void CancelClose() {
m_pg = nullptr;
}
private:
const KPageGroup* m_pg{};
};
} // namespace Kernel
+70 -72
View File
@@ -100,7 +100,7 @@ constexpr size_t GetAddressSpaceWidthFromType(FileSys::ProgramAddressSpaceType a
KPageTable::KPageTable(Core::System& system_)
: m_general_lock{system_.Kernel()},
m_map_physical_memory_lock{system_.Kernel()}, m_system{system_} {}
m_map_physical_memory_lock{system_.Kernel()}, m_system{system_}, m_kernel{system_.Kernel()} {}
KPageTable::~KPageTable() = default;
@@ -373,7 +373,7 @@ Result KPageTable::MapProcessCode(VAddr addr, size_t num_pages, KMemoryState sta
m_memory_block_slab_manager);
// Allocate and open.
KPageGroup pg;
KPageGroup pg{m_kernel, m_block_info_manager};
R_TRY(m_system.Kernel().MemoryManager().AllocateAndOpen(
&pg, num_pages,
KMemoryManager::EncodeOption(KMemoryManager::Pool::Application, m_allocation_option)));
@@ -432,7 +432,7 @@ Result KPageTable::MapCodeMemory(VAddr dst_address, VAddr src_address, size_t si
const size_t num_pages = size / PageSize;
// Create page groups for the memory being mapped.
KPageGroup pg;
KPageGroup pg{m_kernel, m_block_info_manager};
AddRegionToPages(src_address, num_pages, pg);
// Reprotect the source as kernel-read/not mapped.
@@ -593,7 +593,7 @@ Result KPageTable::MakePageGroup(KPageGroup& pg, VAddr addr, size_t num_pages) {
const size_t size = num_pages * PageSize;
// We're making a new group, not adding to an existing one.
R_UNLESS(pg.Empty(), ResultInvalidCurrentMemory);
R_UNLESS(pg.empty(), ResultInvalidCurrentMemory);
// Begin traversal.
Common::PageTable::TraversalContext context;
@@ -640,11 +640,10 @@ Result KPageTable::MakePageGroup(KPageGroup& pg, VAddr addr, size_t num_pages) {
R_SUCCEED();
}
bool KPageTable::IsValidPageGroup(const KPageGroup& pg_ll, VAddr addr, size_t num_pages) {
bool KPageTable::IsValidPageGroup(const KPageGroup& pg, VAddr addr, size_t num_pages) {
ASSERT(this->IsLockedByCurrentThread());
const size_t size = num_pages * PageSize;
const auto& pg = pg_ll.Nodes();
const auto& memory_layout = m_system.Kernel().MemoryLayout();
// Empty groups are necessarily invalid.
@@ -942,9 +941,6 @@ Result KPageTable::SetupForIpcServer(VAddr* out_addr, size_t size, VAddr src_add
ON_RESULT_FAILURE {
if (cur_mapped_addr != dst_addr) {
// HACK: Manually close the pages.
HACK_ClosePages(dst_addr, (cur_mapped_addr - dst_addr) / PageSize);
ASSERT(Operate(dst_addr, (cur_mapped_addr - dst_addr) / PageSize,
KMemoryPermission::None, OperationType::Unmap)
.IsSuccess());
@@ -1020,9 +1016,6 @@ Result KPageTable::SetupForIpcServer(VAddr* out_addr, size_t size, VAddr src_add
// Map the page.
R_TRY(Operate(cur_mapped_addr, 1, test_perm, OperationType::Map, start_partial_page));
// HACK: Manually open the pages.
HACK_OpenPages(start_partial_page, 1);
// Update tracking extents.
cur_mapped_addr += PageSize;
cur_block_addr += PageSize;
@@ -1051,9 +1044,6 @@ Result KPageTable::SetupForIpcServer(VAddr* out_addr, size_t size, VAddr src_add
R_TRY(Operate(cur_mapped_addr, cur_block_size / PageSize, test_perm, OperationType::Map,
cur_block_addr));
// HACK: Manually open the pages.
HACK_OpenPages(cur_block_addr, cur_block_size / PageSize);
// Update tracking extents.
cur_mapped_addr += cur_block_size;
cur_block_addr = next_entry.phys_addr;
@@ -1073,9 +1063,6 @@ Result KPageTable::SetupForIpcServer(VAddr* out_addr, size_t size, VAddr src_add
R_TRY(Operate(cur_mapped_addr, last_block_size / PageSize, test_perm, OperationType::Map,
cur_block_addr));
// HACK: Manually open the pages.
HACK_OpenPages(cur_block_addr, last_block_size / PageSize);
// Update tracking extents.
cur_mapped_addr += last_block_size;
cur_block_addr += last_block_size;
@@ -1107,9 +1094,6 @@ Result KPageTable::SetupForIpcServer(VAddr* out_addr, size_t size, VAddr src_add
// Map the page.
R_TRY(Operate(cur_mapped_addr, 1, test_perm, OperationType::Map, end_partial_page));
// HACK: Manually open the pages.
HACK_OpenPages(end_partial_page, 1);
}
// Update memory blocks to reflect our changes
@@ -1211,9 +1195,6 @@ Result KPageTable::CleanupForIpcServer(VAddr address, size_t size, KMemoryState
const size_t aligned_size = aligned_end - aligned_start;
const size_t aligned_num_pages = aligned_size / PageSize;
// HACK: Manually close the pages.
HACK_ClosePages(aligned_start, aligned_num_pages);
// Unmap the pages.
R_TRY(Operate(aligned_start, aligned_num_pages, KMemoryPermission::None, OperationType::Unmap));
@@ -1501,17 +1482,6 @@ void KPageTable::CleanupForIpcClientOnServerSetupFailure([[maybe_unused]] PageLi
}
}
void KPageTable::HACK_OpenPages(PAddr phys_addr, size_t num_pages) {
m_system.Kernel().MemoryManager().OpenFirst(phys_addr, num_pages);
}
void KPageTable::HACK_ClosePages(VAddr virt_addr, size_t num_pages) {
for (size_t index = 0; index < num_pages; ++index) {
const auto paddr = GetPhysicalAddr(virt_addr + (index * PageSize));
m_system.Kernel().MemoryManager().Close(paddr, 1);
}
}
Result KPageTable::MapPhysicalMemory(VAddr address, size_t size) {
// Lock the physical memory lock.
KScopedLightLock phys_lk(m_map_physical_memory_lock);
@@ -1572,7 +1542,7 @@ Result KPageTable::MapPhysicalMemory(VAddr address, size_t size) {
R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached);
// Allocate pages for the new memory.
KPageGroup pg;
KPageGroup pg{m_kernel, m_block_info_manager};
R_TRY(m_system.Kernel().MemoryManager().AllocateForProcess(
&pg, (size - mapped_size) / PageSize, m_allocate_option, 0, 0));
@@ -1650,7 +1620,7 @@ Result KPageTable::MapPhysicalMemory(VAddr address, size_t size) {
KScopedPageTableUpdater updater(this);
// Prepare to iterate over the memory.
auto pg_it = pg.Nodes().begin();
auto pg_it = pg.begin();
PAddr pg_phys_addr = pg_it->GetAddress();
size_t pg_pages = pg_it->GetNumPages();
@@ -1680,9 +1650,6 @@ Result KPageTable::MapPhysicalMemory(VAddr address, size_t size) {
last_unmap_address + 1 - cur_address) /
PageSize;
// HACK: Manually close the pages.
HACK_ClosePages(cur_address, cur_pages);
// Unmap.
ASSERT(Operate(cur_address, cur_pages, KMemoryPermission::None,
OperationType::Unmap)
@@ -1703,7 +1670,7 @@ Result KPageTable::MapPhysicalMemory(VAddr address, size_t size) {
// Release any remaining unmapped memory.
m_system.Kernel().MemoryManager().OpenFirst(pg_phys_addr, pg_pages);
m_system.Kernel().MemoryManager().Close(pg_phys_addr, pg_pages);
for (++pg_it; pg_it != pg.Nodes().end(); ++pg_it) {
for (++pg_it; pg_it != pg.end(); ++pg_it) {
m_system.Kernel().MemoryManager().OpenFirst(pg_it->GetAddress(),
pg_it->GetNumPages());
m_system.Kernel().MemoryManager().Close(pg_it->GetAddress(),
@@ -1731,7 +1698,7 @@ Result KPageTable::MapPhysicalMemory(VAddr address, size_t size) {
// Check if we're at the end of the physical block.
if (pg_pages == 0) {
// Ensure there are more pages to map.
ASSERT(pg_it != pg.Nodes().end());
ASSERT(pg_it != pg.end());
// Advance our physical block.
++pg_it;
@@ -1742,10 +1709,7 @@ Result KPageTable::MapPhysicalMemory(VAddr address, size_t size) {
// Map whatever we can.
const size_t cur_pages = std::min(pg_pages, map_pages);
R_TRY(Operate(cur_address, cur_pages, KMemoryPermission::UserReadWrite,
OperationType::Map, pg_phys_addr));
// HACK: Manually open the pages.
HACK_OpenPages(pg_phys_addr, cur_pages);
OperationType::MapFirst, pg_phys_addr));
// Advance.
cur_address += cur_pages * PageSize;
@@ -1888,9 +1852,6 @@ Result KPageTable::UnmapPhysicalMemory(VAddr address, size_t size) {
last_address + 1 - cur_address) /
PageSize;
// HACK: Manually close the pages.
HACK_ClosePages(cur_address, cur_pages);
// Unmap.
ASSERT(Operate(cur_address, cur_pages, KMemoryPermission::None, OperationType::Unmap)
.IsSuccess());
@@ -1955,7 +1916,7 @@ Result KPageTable::MapMemory(VAddr dst_address, VAddr src_address, size_t size)
R_TRY(dst_allocator_result);
// Map the memory.
KPageGroup page_linked_list;
KPageGroup page_linked_list{m_kernel, m_block_info_manager};
const size_t num_pages{size / PageSize};
const KMemoryPermission new_src_perm = static_cast<KMemoryPermission>(
KMemoryPermission::KernelRead | KMemoryPermission::NotMapped);
@@ -2022,14 +1983,14 @@ Result KPageTable::UnmapMemory(VAddr dst_address, VAddr src_address, size_t size
num_dst_allocator_blocks);
R_TRY(dst_allocator_result);
KPageGroup src_pages;
KPageGroup dst_pages;
KPageGroup src_pages{m_kernel, m_block_info_manager};
KPageGroup dst_pages{m_kernel, m_block_info_manager};
const size_t num_pages{size / PageSize};
AddRegionToPages(src_address, num_pages, src_pages);
AddRegionToPages(dst_address, num_pages, dst_pages);
R_UNLESS(dst_pages.IsEqual(src_pages), ResultInvalidMemoryRegion);
R_UNLESS(dst_pages.IsEquivalentTo(src_pages), ResultInvalidMemoryRegion);
{
auto block_guard = detail::ScopeExit([&] { MapPages(dst_address, dst_pages, dst_perm); });
@@ -2060,7 +2021,7 @@ Result KPageTable::MapPages(VAddr addr, const KPageGroup& page_linked_list,
VAddr cur_addr{addr};
for (const auto& node : page_linked_list.Nodes()) {
for (const auto& node : page_linked_list) {
if (const auto result{
Operate(cur_addr, node.GetNumPages(), perm, OperationType::Map, node.GetAddress())};
result.IsError()) {
@@ -2160,7 +2121,7 @@ Result KPageTable::UnmapPages(VAddr addr, const KPageGroup& page_linked_list) {
VAddr cur_addr{addr};
for (const auto& node : page_linked_list.Nodes()) {
for (const auto& node : page_linked_list) {
if (const auto result{Operate(cur_addr, node.GetNumPages(), KMemoryPermission::None,
OperationType::Unmap)};
result.IsError()) {
@@ -2527,13 +2488,13 @@ Result KPageTable::SetHeapSize(VAddr* out, size_t size) {
R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached);
// Allocate pages for the heap extension.
KPageGroup pg;
KPageGroup pg{m_kernel, m_block_info_manager};
R_TRY(m_system.Kernel().MemoryManager().AllocateAndOpen(
&pg, allocation_size / PageSize,
KMemoryManager::EncodeOption(m_memory_pool, m_allocation_option)));
// Clear all the newly allocated pages.
for (const auto& it : pg.Nodes()) {
for (const auto& it : pg) {
std::memset(m_system.DeviceMemory().GetPointer<void>(it.GetAddress()), m_heap_fill_value,
it.GetSize());
}
@@ -2610,11 +2571,23 @@ ResultVal<VAddr> KPageTable::AllocateAndMapMemory(size_t needed_num_pages, size_
if (is_map_only) {
R_TRY(Operate(addr, needed_num_pages, perm, OperationType::Map, map_addr));
} else {
KPageGroup page_group;
R_TRY(m_system.Kernel().MemoryManager().AllocateForProcess(
&page_group, needed_num_pages,
KMemoryManager::EncodeOption(m_memory_pool, m_allocation_option), 0, 0));
R_TRY(Operate(addr, needed_num_pages, page_group, OperationType::MapGroup));
// Create a page group tohold the pages we allocate.
KPageGroup pg{m_kernel, m_block_info_manager};
R_TRY(m_system.Kernel().MemoryManager().AllocateAndOpen(
&pg, needed_num_pages,
KMemoryManager::EncodeOption(m_memory_pool, m_allocation_option)));
// Ensure that the page group is closed when we're done working with it.
SCOPE_EXIT({ pg.Close(); });
// Clear all pages.
for (const auto& it : pg) {
std::memset(m_system.DeviceMemory().GetPointer<void>(it.GetAddress()),
m_heap_fill_value, it.GetSize());
}
R_TRY(Operate(addr, needed_num_pages, pg, OperationType::MapGroup));
}
// Update the blocks.
@@ -2795,19 +2768,28 @@ Result KPageTable::Operate(VAddr addr, size_t num_pages, const KPageGroup& page_
ASSERT(num_pages > 0);
ASSERT(num_pages == page_group.GetNumPages());
for (const auto& node : page_group.Nodes()) {
const size_t size{node.GetNumPages() * PageSize};
switch (operation) {
case OperationType::MapGroup: {
// We want to maintain a new reference to every page in the group.
KScopedPageGroup spg(page_group);
switch (operation) {
case OperationType::MapGroup:
for (const auto& node : page_group) {
const size_t size{node.GetNumPages() * PageSize};
// Map the pages.
m_system.Memory().MapMemoryRegion(*m_page_table_impl, addr, size, node.GetAddress());
break;
default:
ASSERT(false);
break;
addr += size;
}
addr += size;
// We succeeded! We want to persist the reference to the pages.
spg.CancelClose();
break;
}
default:
ASSERT(false);
break;
}
R_SUCCEED();
@@ -2822,13 +2804,29 @@ Result KPageTable::Operate(VAddr addr, size_t num_pages, KMemoryPermission perm,
ASSERT(ContainsPages(addr, num_pages));
switch (operation) {
case OperationType::Unmap:
case OperationType::Unmap: {
// Ensure that any pages we track close on exit.
KPageGroup pages_to_close{m_kernel, this->GetBlockInfoManager()};
SCOPE_EXIT({ pages_to_close.CloseAndReset(); });
this->AddRegionToPages(addr, num_pages, pages_to_close);
m_system.Memory().UnmapRegion(*m_page_table_impl, addr, num_pages * PageSize);
break;
}
case OperationType::MapFirst:
case OperationType::Map: {
ASSERT(map_addr);
ASSERT(Common::IsAligned(map_addr, PageSize));
m_system.Memory().MapMemoryRegion(*m_page_table_impl, addr, num_pages * PageSize, map_addr);
// Open references to pages, if we should.
if (IsHeapPhysicalAddress(m_kernel.MemoryLayout(), map_addr)) {
if (operation == OperationType::MapFirst) {
m_kernel.MemoryManager().OpenFirst(map_addr, num_pages);
} else {
m_kernel.MemoryManager().Open(map_addr, num_pages);
}
}
break;
}
case OperationType::Separate: {
+5 -4
View File
@@ -107,6 +107,10 @@ public:
return *m_page_table_impl;
}
KBlockInfoManager* GetBlockInfoManager() {
return m_block_info_manager;
}
bool CanContain(VAddr addr, size_t size, KMemoryState state) const;
protected:
@@ -261,10 +265,6 @@ private:
void CleanupForIpcClientOnServerSetupFailure(PageLinkedList* page_list, VAddr address,
size_t size, KMemoryPermission prot_perm);
// HACK: These will be removed once we automatically manage page reference counts.
void HACK_OpenPages(PAddr phys_addr, size_t num_pages);
void HACK_ClosePages(VAddr virt_addr, size_t num_pages);
mutable KLightLock m_general_lock;
mutable KLightLock m_map_physical_memory_lock;
@@ -488,6 +488,7 @@ private:
std::unique_ptr<Common::PageTable> m_page_table_impl;
Core::System& m_system;
KernelCore& m_kernel;
};
} // namespace Kernel
+11
View File
@@ -285,6 +285,17 @@ void KProcess::UnregisterThread(KThread* thread) {
thread_list.remove(thread);
}
u64 KProcess::GetFreeThreadCount() const {
if (resource_limit != nullptr) {
const auto current_value =
resource_limit->GetCurrentValue(LimitableResource::ThreadCountMax);
const auto limit_value = resource_limit->GetLimitValue(LimitableResource::ThreadCountMax);
return limit_value - current_value;
} else {
return 0;
}
}
Result KProcess::Reset() {
// Lock the process and the scheduler.
KScopedLightLock lk(state_lock);
+3
View File
@@ -304,6 +304,9 @@ public:
/// from this process' thread list.
void UnregisterThread(KThread* thread);
/// Retrieves the number of available threads for this process.
u64 GetFreeThreadCount() const;
/// Clears the signaled state of the process if and only if it's signaled.
///
/// @pre The process must not be already terminated. If this is called on a
@@ -5,9 +5,9 @@
#include "common/common_types.h"
#include "core/hle/kernel/global_scheduler_context.h"
#include "core/hle/kernel/k_hardware_timer.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/time_manager.h"
namespace Kernel {
@@ -22,7 +22,7 @@ public:
~KScopedSchedulerLockAndSleep() {
// Register the sleep.
if (timeout_tick > 0) {
kernel.TimeManager().ScheduleTimeEvent(thread, timeout_tick);
kernel.HardwareTimer().RegisterTask(thread, timeout_tick);
}
// Unlock the scheduler.
+41 -29
View File
@@ -6,31 +6,29 @@
#include "core/hle/kernel/k_page_table.h"
#include "core/hle/kernel/k_scoped_resource_reservation.h"
#include "core/hle/kernel/k_shared_memory.h"
#include "core/hle/kernel/k_system_resource.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel {
KSharedMemory::KSharedMemory(KernelCore& kernel_) : KAutoObjectWithSlabHeapAndContainer{kernel_} {}
KSharedMemory::~KSharedMemory() {
kernel.GetSystemResourceLimit()->Release(LimitableResource::PhysicalMemoryMax, size);
}
KSharedMemory::~KSharedMemory() = default;
Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory_, KProcess* owner_process_,
KPageGroup&& page_list_, Svc::MemoryPermission owner_permission_,
Svc::MemoryPermission user_permission_, PAddr physical_address_,
std::size_t size_, std::string name_) {
Svc::MemoryPermission owner_permission_,
Svc::MemoryPermission user_permission_, std::size_t size_,
std::string name_) {
// Set members.
owner_process = owner_process_;
device_memory = &device_memory_;
page_list = std::move(page_list_);
owner_permission = owner_permission_;
user_permission = user_permission_;
physical_address = physical_address_;
size = size_;
size = Common::AlignUp(size_, PageSize);
name = std::move(name_);
const size_t num_pages = Common::DivideUp(size, PageSize);
// Get the resource limit.
KResourceLimit* reslimit = kernel.GetSystemResourceLimit();
@@ -39,6 +37,18 @@ Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory_, KProcess* o
size_);
R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached);
// Allocate the memory.
//! HACK: Open continuous mapping from sysmodule pool.
auto option = KMemoryManager::EncodeOption(KMemoryManager::Pool::Secure,
KMemoryManager::Direction::FromBack);
physical_address = kernel.MemoryManager().AllocateAndOpenContinuous(num_pages, 1, option);
R_UNLESS(physical_address != 0, ResultOutOfMemory);
//! Insert the result into our page group.
page_group.emplace(kernel, &kernel.GetSystemSystemResource().GetBlockInfoManager());
page_group->AddBlock(physical_address, num_pages);
// Commit our reservation.
memory_reservation.Commit();
@@ -50,12 +60,18 @@ Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory_, KProcess* o
is_initialized = true;
// Clear all pages in the memory.
std::memset(device_memory_.GetPointer<void>(physical_address_), 0, size_);
for (const auto& block : *page_group) {
std::memset(device_memory_.GetPointer<void>(block.GetAddress()), 0, block.GetSize());
}
return ResultSuccess;
}
void KSharedMemory::Finalize() {
// Close and finalize the page group.
page_group->Close();
page_group->Finalize();
// Release the memory reservation.
resource_limit->Release(LimitableResource::PhysicalMemoryMax, size);
resource_limit->Close();
@@ -65,32 +81,28 @@ void KSharedMemory::Finalize() {
}
Result KSharedMemory::Map(KProcess& target_process, VAddr address, std::size_t map_size,
Svc::MemoryPermission permissions) {
const u64 page_count{(map_size + PageSize - 1) / PageSize};
Svc::MemoryPermission map_perm) {
// Validate the size.
R_UNLESS(size == map_size, ResultInvalidSize);
if (page_list.GetNumPages() != page_count) {
UNIMPLEMENTED_MSG("Page count does not match");
}
const Svc::MemoryPermission expected =
// Validate the permission.
const Svc::MemoryPermission test_perm =
&target_process == owner_process ? owner_permission : user_permission;
if (permissions != expected) {
UNIMPLEMENTED_MSG("Permission does not match");
if (test_perm == Svc::MemoryPermission::DontCare) {
ASSERT(map_perm == Svc::MemoryPermission::Read || map_perm == Svc::MemoryPermission::Write);
} else {
R_UNLESS(map_perm == test_perm, ResultInvalidNewMemoryPermission);
}
return target_process.PageTable().MapPages(address, page_list, KMemoryState::Shared,
ConvertToKMemoryPermission(permissions));
return target_process.PageTable().MapPages(address, *page_group, KMemoryState::Shared,
ConvertToKMemoryPermission(map_perm));
}
Result KSharedMemory::Unmap(KProcess& target_process, VAddr address, std::size_t unmap_size) {
const u64 page_count{(unmap_size + PageSize - 1) / PageSize};
// Validate the size.
R_UNLESS(size == unmap_size, ResultInvalidSize);
if (page_list.GetNumPages() != page_count) {
UNIMPLEMENTED_MSG("Page count does not match");
}
return target_process.PageTable().UnmapPages(address, page_list, KMemoryState::Shared);
return target_process.PageTable().UnmapPages(address, *page_group, KMemoryState::Shared);
}
} // namespace Kernel
+4 -4
View File
@@ -3,6 +3,7 @@
#pragma once
#include <optional>
#include <string>
#include "common/common_types.h"
@@ -26,9 +27,8 @@ public:
~KSharedMemory() override;
Result Initialize(Core::DeviceMemory& device_memory_, KProcess* owner_process_,
KPageGroup&& page_list_, Svc::MemoryPermission owner_permission_,
Svc::MemoryPermission user_permission_, PAddr physical_address_,
std::size_t size_, std::string name_);
Svc::MemoryPermission owner_permission_,
Svc::MemoryPermission user_permission_, std::size_t size_, std::string name_);
/**
* Maps a shared memory block to an address in the target process' address space
@@ -76,7 +76,7 @@ public:
private:
Core::DeviceMemory* device_memory{};
KProcess* owner_process{};
KPageGroup page_list;
std::optional<KPageGroup> page_group{};
Svc::MemoryPermission owner_permission{};
Svc::MemoryPermission user_permission{};
PAddr physical_address{};
+7 -1
View File
@@ -22,6 +22,7 @@
#include "core/hle/kernel/k_light_lock.h"
#include "core/hle/kernel/k_spin_lock.h"
#include "core/hle/kernel/k_synchronization_object.h"
#include "core/hle/kernel/k_timer_task.h"
#include "core/hle/kernel/k_worker_task.h"
#include "core/hle/kernel/slab_helpers.h"
#include "core/hle/kernel/svc_common.h"
@@ -112,7 +113,8 @@ void SetCurrentThread(KernelCore& kernel, KThread* thread);
[[nodiscard]] s32 GetCurrentCoreId(KernelCore& kernel);
class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KWorkerTask>,
public boost::intrusive::list_base_hook<> {
public boost::intrusive::list_base_hook<>,
public KTimerTask {
KERNEL_AUTOOBJECT_TRAITS(KThread, KSynchronizationObject);
private:
@@ -840,4 +842,8 @@ private:
KernelCore& kernel;
};
inline void KTimerTask::OnTimer() {
static_cast<KThread*>(this)->OnTimer();
}
} // namespace Kernel
+3 -3
View File
@@ -1,9 +1,9 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/kernel/k_hardware_timer.h"
#include "core/hle/kernel/k_thread_queue.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/time_manager.h"
namespace Kernel {
@@ -22,7 +22,7 @@ void KThreadQueue::EndWait(KThread* waiting_thread, Result wait_result) {
waiting_thread->ClearWaitQueue();
// Cancel the thread task.
kernel.TimeManager().UnscheduleTimeEvent(waiting_thread);
kernel.HardwareTimer().CancelTask(waiting_thread);
}
void KThreadQueue::CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) {
@@ -37,7 +37,7 @@ void KThreadQueue::CancelWait(KThread* waiting_thread, Result wait_result, bool
// Cancel the thread task.
if (cancel_timer_task) {
kernel.TimeManager().UnscheduleTimeEvent(waiting_thread);
kernel.HardwareTimer().CancelTask(waiting_thread);
}
}
+40
View File
@@ -0,0 +1,40 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/intrusive_red_black_tree.h"
namespace Kernel {
class KTimerTask : public Common::IntrusiveRedBlackTreeBaseNode<KTimerTask> {
public:
static constexpr int Compare(const KTimerTask& lhs, const KTimerTask& rhs) {
if (lhs.GetTime() < rhs.GetTime()) {
return -1;
} else {
return 1;
}
}
constexpr explicit KTimerTask() = default;
constexpr void SetTime(s64 t) {
m_time = t;
}
constexpr s64 GetTime() const {
return m_time;
}
// NOTE: This is virtual in Nintendo's kernel. Prior to 13.0.0, KWaitObject was also a
// TimerTask; this is no longer the case. Since this is now KThread exclusive, we have
// devirtualized (see inline declaration for this inside k_thread.h).
void OnTimer();
private:
// Absolute time in nanoseconds
s64 m_time{};
};
} // namespace Kernel
+25 -38
View File
@@ -26,6 +26,7 @@
#include "core/hle/kernel/k_client_port.h"
#include "core/hle/kernel/k_dynamic_resource_manager.h"
#include "core/hle/kernel/k_handle_table.h"
#include "core/hle/kernel/k_hardware_timer.h"
#include "core/hle/kernel/k_memory_layout.h"
#include "core/hle/kernel/k_memory_manager.h"
#include "core/hle/kernel/k_page_buffer.h"
@@ -39,7 +40,6 @@
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/physical_core.h"
#include "core/hle/kernel/service_thread.h"
#include "core/hle/kernel/time_manager.h"
#include "core/hle/result.h"
#include "core/hle/service/sm/sm.h"
#include "core/memory.h"
@@ -55,7 +55,7 @@ struct KernelCore::Impl {
static constexpr size_t ReservedDynamicPageCount = 64;
explicit Impl(Core::System& system_, KernelCore& kernel_)
: time_manager{system_}, service_threads_manager{1, "ServiceThreadsManager"},
: service_threads_manager{1, "ServiceThreadsManager"},
service_thread_barrier{2}, system{system_} {}
void SetMulticore(bool is_multi) {
@@ -63,6 +63,9 @@ struct KernelCore::Impl {
}
void Initialize(KernelCore& kernel) {
hardware_timer = std::make_unique<Kernel::KHardwareTimer>(kernel);
hardware_timer->Initialize();
global_object_list_container = std::make_unique<KAutoObjectWithListContainer>(kernel);
global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel);
global_handle_table = std::make_unique<Kernel::KHandleTable>(kernel);
@@ -91,6 +94,7 @@ struct KernelCore::Impl {
pt_heap_region.GetSize());
}
InitializeHackSharedMemory();
RegisterHostThread(nullptr);
default_service_thread = &CreateServiceThread(kernel, "DefaultServiceThread");
@@ -193,6 +197,9 @@ struct KernelCore::Impl {
// Ensure that the object list container is finalized and properly shutdown.
global_object_list_container->Finalize();
global_object_list_container.reset();
hardware_timer->Finalize();
hardware_timer.reset();
}
void CloseServices() {
@@ -720,14 +727,14 @@ struct KernelCore::Impl {
}
void InitializeMemoryLayout() {
const auto system_pool = memory_layout->GetKernelSystemPoolRegionPhysicalExtents();
// Initialize the memory manager.
memory_manager = std::make_unique<KMemoryManager>(system);
const auto& management_region = memory_layout->GetPoolManagementRegion();
ASSERT(management_region.GetEndAddress() != 0);
memory_manager->Initialize(management_region.GetAddress(), management_region.GetSize());
}
void InitializeHackSharedMemory() {
// Setup memory regions for emulated processes
// TODO(bunnei): These should not be hardcoded regions initialized within the kernel
constexpr std::size_t hid_size{0x40000};
@@ -736,39 +743,23 @@ struct KernelCore::Impl {
constexpr std::size_t time_size{0x1000};
constexpr std::size_t hidbus_size{0x1000};
const PAddr hid_phys_addr{system_pool.GetAddress()};
const PAddr font_phys_addr{system_pool.GetAddress() + hid_size};
const PAddr irs_phys_addr{system_pool.GetAddress() + hid_size + font_size};
const PAddr time_phys_addr{system_pool.GetAddress() + hid_size + font_size + irs_size};
const PAddr hidbus_phys_addr{system_pool.GetAddress() + hid_size + font_size + irs_size +
time_size};
hid_shared_mem = KSharedMemory::Create(system.Kernel());
font_shared_mem = KSharedMemory::Create(system.Kernel());
irs_shared_mem = KSharedMemory::Create(system.Kernel());
time_shared_mem = KSharedMemory::Create(system.Kernel());
hidbus_shared_mem = KSharedMemory::Create(system.Kernel());
hid_shared_mem->Initialize(system.DeviceMemory(), nullptr,
{hid_phys_addr, hid_size / PageSize},
Svc::MemoryPermission::None, Svc::MemoryPermission::Read,
hid_phys_addr, hid_size, "HID:SharedMemory");
font_shared_mem->Initialize(system.DeviceMemory(), nullptr,
{font_phys_addr, font_size / PageSize},
Svc::MemoryPermission::None, Svc::MemoryPermission::Read,
font_phys_addr, font_size, "Font:SharedMemory");
irs_shared_mem->Initialize(system.DeviceMemory(), nullptr,
{irs_phys_addr, irs_size / PageSize},
Svc::MemoryPermission::None, Svc::MemoryPermission::Read,
irs_phys_addr, irs_size, "IRS:SharedMemory");
time_shared_mem->Initialize(system.DeviceMemory(), nullptr,
{time_phys_addr, time_size / PageSize},
Svc::MemoryPermission::None, Svc::MemoryPermission::Read,
time_phys_addr, time_size, "Time:SharedMemory");
hidbus_shared_mem->Initialize(system.DeviceMemory(), nullptr,
{hidbus_phys_addr, hidbus_size / PageSize},
Svc::MemoryPermission::None, Svc::MemoryPermission::Read,
hidbus_phys_addr, hidbus_size, "HidBus:SharedMemory");
hid_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None,
Svc::MemoryPermission::Read, hid_size, "HID:SharedMemory");
font_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None,
Svc::MemoryPermission::Read, font_size, "Font:SharedMemory");
irs_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None,
Svc::MemoryPermission::Read, irs_size, "IRS:SharedMemory");
time_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None,
Svc::MemoryPermission::Read, time_size, "Time:SharedMemory");
hidbus_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None,
Svc::MemoryPermission::Read, hidbus_size,
"HidBus:SharedMemory");
}
KClientPort* CreateNamedServicePort(std::string name) {
@@ -832,7 +823,7 @@ struct KernelCore::Impl {
std::vector<KProcess*> process_list;
std::atomic<KProcess*> current_process{};
std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context;
Kernel::TimeManager time_manager;
std::unique_ptr<Kernel::KHardwareTimer> hardware_timer;
Init::KSlabResourceCounts slab_resource_counts{};
KResourceLimit* system_resource_limit{};
@@ -1019,12 +1010,8 @@ Kernel::KScheduler* KernelCore::CurrentScheduler() {
return impl->schedulers[core_id].get();
}
Kernel::TimeManager& KernelCore::TimeManager() {
return impl->time_manager;
}
const Kernel::TimeManager& KernelCore::TimeManager() const {
return impl->time_manager;
Kernel::KHardwareTimer& KernelCore::HardwareTimer() {
return *impl->hardware_timer;
}
Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() {
+3 -6
View File
@@ -39,6 +39,7 @@ class KDynamicPageManager;
class KEvent;
class KEventInfo;
class KHandleTable;
class KHardwareTimer;
class KLinkedListNode;
class KMemoryLayout;
class KMemoryManager;
@@ -63,7 +64,6 @@ class KCodeMemory;
class PhysicalCore;
class ServiceThread;
class Synchronization;
class TimeManager;
using ServiceInterfaceFactory =
std::function<KClientPort&(Service::SM::ServiceManager&, Core::System&)>;
@@ -175,11 +175,8 @@ public:
/// Gets the an instance of the current physical CPU core.
const Kernel::PhysicalCore& CurrentPhysicalCore() const;
/// Gets the an instance of the TimeManager Interface.
Kernel::TimeManager& TimeManager();
/// Gets the an instance of the TimeManager Interface.
const Kernel::TimeManager& TimeManager() const;
/// Gets the an instance of the hardware timer.
Kernel::KHardwareTimer& HardwareTimer();
/// Stops execution of 'id' core, in order to reschedule a new thread.
void PrepareReschedule(std::size_t id);
+3
View File
@@ -14,4 +14,7 @@ constexpr std::size_t PageSize{1 << PageBits};
using Page = std::array<u8, PageSize>;
using KPhysicalAddress = PAddr;
using KProcessAddress = VAddr;
} // namespace Kernel
+51 -81
View File
@@ -784,63 +784,29 @@ static Result GetInfo(Core::System& system, u64* result, u64 info_id, Handle han
LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id,
info_sub_id, handle);
enum class GetInfoType : u64 {
// 1.0.0+
AllowedCPUCoreMask = 0,
AllowedThreadPriorityMask = 1,
MapRegionBaseAddr = 2,
MapRegionSize = 3,
HeapRegionBaseAddr = 4,
HeapRegionSize = 5,
TotalPhysicalMemoryAvailable = 6,
TotalPhysicalMemoryUsed = 7,
IsCurrentProcessBeingDebugged = 8,
RegisterResourceLimit = 9,
IdleTickCount = 10,
RandomEntropy = 11,
ThreadTickCount = 0xF0000002,
// 2.0.0+
ASLRRegionBaseAddr = 12,
ASLRRegionSize = 13,
StackRegionBaseAddr = 14,
StackRegionSize = 15,
// 3.0.0+
SystemResourceSize = 16,
SystemResourceUsage = 17,
TitleId = 18,
// 4.0.0+
PrivilegedProcessId = 19,
// 5.0.0+
UserExceptionContextAddr = 20,
// 6.0.0+
TotalPhysicalMemoryAvailableWithoutSystemResource = 21,
TotalPhysicalMemoryUsedWithoutSystemResource = 22,
// Homebrew only
MesosphereCurrentProcess = 65001,
};
const auto info_id_type = static_cast<GetInfoType>(info_id);
const auto info_id_type = static_cast<InfoType>(info_id);
switch (info_id_type) {
case GetInfoType::AllowedCPUCoreMask:
case GetInfoType::AllowedThreadPriorityMask:
case GetInfoType::MapRegionBaseAddr:
case GetInfoType::MapRegionSize:
case GetInfoType::HeapRegionBaseAddr:
case GetInfoType::HeapRegionSize:
case GetInfoType::ASLRRegionBaseAddr:
case GetInfoType::ASLRRegionSize:
case GetInfoType::StackRegionBaseAddr:
case GetInfoType::StackRegionSize:
case GetInfoType::TotalPhysicalMemoryAvailable:
case GetInfoType::TotalPhysicalMemoryUsed:
case GetInfoType::SystemResourceSize:
case GetInfoType::SystemResourceUsage:
case GetInfoType::TitleId:
case GetInfoType::UserExceptionContextAddr:
case GetInfoType::TotalPhysicalMemoryAvailableWithoutSystemResource:
case GetInfoType::TotalPhysicalMemoryUsedWithoutSystemResource: {
case InfoType::CoreMask:
case InfoType::PriorityMask:
case InfoType::AliasRegionAddress:
case InfoType::AliasRegionSize:
case InfoType::HeapRegionAddress:
case InfoType::HeapRegionSize:
case InfoType::AslrRegionAddress:
case InfoType::AslrRegionSize:
case InfoType::StackRegionAddress:
case InfoType::StackRegionSize:
case InfoType::TotalMemorySize:
case InfoType::UsedMemorySize:
case InfoType::SystemResourceSizeTotal:
case InfoType::SystemResourceSizeUsed:
case InfoType::ProgramId:
case InfoType::UserExceptionContextAddress:
case InfoType::TotalNonSystemMemorySize:
case InfoType::UsedNonSystemMemorySize:
case InfoType::IsApplication:
case InfoType::FreeThreadCount: {
if (info_sub_id != 0) {
LOG_ERROR(Kernel_SVC, "Info sub id is non zero! info_id={}, info_sub_id={}", info_id,
info_sub_id);
@@ -856,79 +822,83 @@ static Result GetInfo(Core::System& system, u64* result, u64 info_id, Handle han
}
switch (info_id_type) {
case GetInfoType::AllowedCPUCoreMask:
case InfoType::CoreMask:
*result = process->GetCoreMask();
return ResultSuccess;
case GetInfoType::AllowedThreadPriorityMask:
case InfoType::PriorityMask:
*result = process->GetPriorityMask();
return ResultSuccess;
case GetInfoType::MapRegionBaseAddr:
case InfoType::AliasRegionAddress:
*result = process->PageTable().GetAliasRegionStart();
return ResultSuccess;
case GetInfoType::MapRegionSize:
case InfoType::AliasRegionSize:
*result = process->PageTable().GetAliasRegionSize();
return ResultSuccess;
case GetInfoType::HeapRegionBaseAddr:
case InfoType::HeapRegionAddress:
*result = process->PageTable().GetHeapRegionStart();
return ResultSuccess;
case GetInfoType::HeapRegionSize:
case InfoType::HeapRegionSize:
*result = process->PageTable().GetHeapRegionSize();
return ResultSuccess;
case GetInfoType::ASLRRegionBaseAddr:
case InfoType::AslrRegionAddress:
*result = process->PageTable().GetAliasCodeRegionStart();
return ResultSuccess;
case GetInfoType::ASLRRegionSize:
case InfoType::AslrRegionSize:
*result = process->PageTable().GetAliasCodeRegionSize();
return ResultSuccess;
case GetInfoType::StackRegionBaseAddr:
case InfoType::StackRegionAddress:
*result = process->PageTable().GetStackRegionStart();
return ResultSuccess;
case GetInfoType::StackRegionSize:
case InfoType::StackRegionSize:
*result = process->PageTable().GetStackRegionSize();
return ResultSuccess;
case GetInfoType::TotalPhysicalMemoryAvailable:
case InfoType::TotalMemorySize:
*result = process->GetTotalPhysicalMemoryAvailable();
return ResultSuccess;
case GetInfoType::TotalPhysicalMemoryUsed:
case InfoType::UsedMemorySize:
*result = process->GetTotalPhysicalMemoryUsed();
return ResultSuccess;
case GetInfoType::SystemResourceSize:
case InfoType::SystemResourceSizeTotal:
*result = process->GetSystemResourceSize();
return ResultSuccess;
case GetInfoType::SystemResourceUsage:
case InfoType::SystemResourceSizeUsed:
LOG_WARNING(Kernel_SVC, "(STUBBED) Attempted to query system resource usage");
*result = process->GetSystemResourceUsage();
return ResultSuccess;
case GetInfoType::TitleId:
case InfoType::ProgramId:
*result = process->GetProgramID();
return ResultSuccess;
case GetInfoType::UserExceptionContextAddr:
case InfoType::UserExceptionContextAddress:
*result = process->GetProcessLocalRegionAddress();
return ResultSuccess;
case GetInfoType::TotalPhysicalMemoryAvailableWithoutSystemResource:
case InfoType::TotalNonSystemMemorySize:
*result = process->GetTotalPhysicalMemoryAvailableWithoutSystemResource();
return ResultSuccess;
case GetInfoType::TotalPhysicalMemoryUsedWithoutSystemResource:
case InfoType::UsedNonSystemMemorySize:
*result = process->GetTotalPhysicalMemoryUsedWithoutSystemResource();
return ResultSuccess;
case InfoType::FreeThreadCount:
*result = process->GetFreeThreadCount();
return ResultSuccess;
default:
break;
}
@@ -937,11 +907,11 @@ static Result GetInfo(Core::System& system, u64* result, u64 info_id, Handle han
return ResultInvalidEnumValue;
}
case GetInfoType::IsCurrentProcessBeingDebugged:
case InfoType::DebuggerAttached:
*result = 0;
return ResultSuccess;
case GetInfoType::RegisterResourceLimit: {
case InfoType::ResourceLimit: {
if (handle != 0) {
LOG_ERROR(Kernel, "Handle is non zero! handle={:08X}", handle);
return ResultInvalidHandle;
@@ -969,7 +939,7 @@ static Result GetInfo(Core::System& system, u64* result, u64 info_id, Handle han
return ResultSuccess;
}
case GetInfoType::RandomEntropy:
case InfoType::RandomEntropy:
if (handle != 0) {
LOG_ERROR(Kernel_SVC, "Process Handle is non zero, expected 0 result but got {:016X}",
handle);
@@ -985,13 +955,13 @@ static Result GetInfo(Core::System& system, u64* result, u64 info_id, Handle han
*result = system.Kernel().CurrentProcess()->GetRandomEntropy(info_sub_id);
return ResultSuccess;
case GetInfoType::PrivilegedProcessId:
case InfoType::InitialProcessIdRange:
LOG_WARNING(Kernel_SVC,
"(STUBBED) Attempted to query privileged process id bounds, returned 0");
*result = 0;
return ResultSuccess;
case GetInfoType::ThreadTickCount: {
case InfoType::ThreadTickCount: {
constexpr u64 num_cpus = 4;
if (info_sub_id != 0xFFFFFFFFFFFFFFFF && info_sub_id >= num_cpus) {
LOG_ERROR(Kernel_SVC, "Core count is out of range, expected {} but got {}", num_cpus,
@@ -1026,7 +996,7 @@ static Result GetInfo(Core::System& system, u64* result, u64 info_id, Handle han
*result = out_ticks;
return ResultSuccess;
}
case GetInfoType::IdleTickCount: {
case InfoType::IdleTickCount: {
// Verify the input handle is invalid.
R_UNLESS(handle == InvalidHandle, ResultInvalidHandle);
@@ -1040,7 +1010,7 @@ static Result GetInfo(Core::System& system, u64* result, u64 info_id, Handle han
*result = system.Kernel().CurrentScheduler()->GetIdleThread()->GetCpuTime();
return ResultSuccess;
}
case GetInfoType::MesosphereCurrentProcess: {
case InfoType::MesosphereCurrentProcess: {
// Verify the input handle is invalid.
R_UNLESS(handle == InvalidHandle, ResultInvalidHandle);
@@ -1515,7 +1485,7 @@ static Result MapProcessMemory(Core::System& system, VAddr dst_address, Handle p
ResultInvalidMemoryRegion);
// Create a new page group.
KPageGroup pg;
KPageGroup pg{system.Kernel(), dst_pt.GetBlockInfoManager()};
R_TRY(src_pt.MakeAndOpenPageGroup(
std::addressof(pg), src_address, size / PageSize, KMemoryState::FlagCanMapProcess,
KMemoryState::FlagCanMapProcess, KMemoryPermission::None, KMemoryPermission::None,
-44
View File
@@ -1,44 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/assert.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/time_manager.h"
namespace Kernel {
TimeManager::TimeManager(Core::System& system_) : system{system_} {
time_manager_event_type = Core::Timing::CreateEvent(
"Kernel::TimeManagerCallback",
[this](std::uintptr_t thread_handle, s64 time,
std::chrono::nanoseconds) -> std::optional<std::chrono::nanoseconds> {
KThread* thread = reinterpret_cast<KThread*>(thread_handle);
{
KScopedSchedulerLock sl(system.Kernel());
thread->OnTimer();
}
return std::nullopt;
});
}
void TimeManager::ScheduleTimeEvent(KThread* thread, s64 nanoseconds) {
std::scoped_lock lock{mutex};
if (nanoseconds > 0) {
ASSERT(thread);
ASSERT(thread->GetState() != ThreadState::Runnable);
system.CoreTiming().ScheduleEvent(std::chrono::nanoseconds{nanoseconds},
time_manager_event_type,
reinterpret_cast<uintptr_t>(thread));
}
}
void TimeManager::UnscheduleTimeEvent(KThread* thread) {
std::scoped_lock lock{mutex};
system.CoreTiming().UnscheduleEvent(time_manager_event_type,
reinterpret_cast<uintptr_t>(thread));
}
} // namespace Kernel
-41
View File
@@ -1,41 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <memory>
#include <mutex>
namespace Core {
class System;
} // namespace Core
namespace Core::Timing {
struct EventType;
} // namespace Core::Timing
namespace Kernel {
class KThread;
/**
* The `TimeManager` takes care of scheduling time events on threads and executes their TimeUp
* method when the event is triggered.
*/
class TimeManager {
public:
explicit TimeManager(Core::System& system);
/// Schedule a time event on `timetask` thread that will expire in 'nanoseconds'
void ScheduleTimeEvent(KThread* time_task, s64 nanoseconds);
/// Unschedule an existing time event
void UnscheduleTimeEvent(KThread* thread);
private:
Core::System& system;
std::shared_ptr<Core::Timing::EventType> time_manager_event_type;
std::mutex mutex;
};
} // namespace Kernel
+3 -2
View File
@@ -203,8 +203,9 @@ private:
};
AudInU::AudInU(Core::System& system_)
: ServiceFramework{system_, "audin:u"}, service_context{system_, "AudInU"},
impl{std::make_unique<AudioCore::AudioIn::Manager>(system_)} {
: ServiceFramework{system_, "audin:u", ServiceThreadType::CreateNew},
service_context{system_, "AudInU"}, impl{std::make_unique<AudioCore::AudioIn::Manager>(
system_)} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &AudInU::ListAudioIns, "ListAudioIns"},
+6 -4
View File
@@ -26,8 +26,9 @@ public:
explicit IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager,
size_t session_id, const std::string& device_name,
const AudioOutParameter& in_params, u32 handle, u64 applet_resource_user_id)
: ServiceFramework{system_, "IAudioOut"}, service_context{system_, "IAudioOut"},
event{service_context.CreateEvent("AudioOutEvent")},
: ServiceFramework{system_, "IAudioOut", ServiceThreadType::CreateNew},
service_context{system_, "IAudioOut"}, event{service_context.CreateEvent(
"AudioOutEvent")},
impl{std::make_shared<AudioCore::AudioOut::Out>(system_, manager, event, session_id)} {
// clang-format off
@@ -220,8 +221,9 @@ private:
};
AudOutU::AudOutU(Core::System& system_)
: ServiceFramework{system_, "audout:u"}, service_context{system_, "AudOutU"},
impl{std::make_unique<AudioCore::AudioOut::Manager>(system_)} {
: ServiceFramework{system_, "audout:u", ServiceThreadType::CreateNew},
service_context{system_, "AudOutU"}, impl{std::make_unique<AudioCore::AudioOut::Manager>(
system_)} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &AudOutU::ListAudioOuts, "ListAudioOuts"},
+9 -6
View File
@@ -35,9 +35,10 @@ public:
AudioCore::AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
u32 process_handle, u64 applet_resource_user_id, s32 session_id)
: ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"},
rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_},
impl{std::make_unique<Renderer>(system_, manager, rendered_event)} {
: ServiceFramework{system_, "IAudioRenderer", ServiceThreadType::CreateNew},
service_context{system_, "IAudioRenderer"}, rendered_event{service_context.CreateEvent(
"IAudioRendererEvent")},
manager{manager_}, impl{std::make_unique<Renderer>(system_, manager, rendered_event)} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &IAudioRenderer::GetSampleRate, "GetSampleRate"},
@@ -242,8 +243,10 @@ class IAudioDevice final : public ServiceFramework<IAudioDevice> {
public:
explicit IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u32 revision,
u32 device_num)
: ServiceFramework{system_, "IAudioDevice"}, service_context{system_, "IAudioDevice"},
impl{std::make_unique<AudioDevice>(system_, applet_resource_user_id, revision)},
: ServiceFramework{system_, "IAudioDevice", ServiceThreadType::CreateNew},
service_context{system_, "IAudioDevice"}, impl{std::make_unique<AudioDevice>(
system_, applet_resource_user_id,
revision)},
event{service_context.CreateEvent(fmt::format("IAudioDeviceEvent-{}", device_num))} {
static const FunctionInfo functions[] = {
{0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"},
@@ -418,7 +421,7 @@ private:
};
AudRenU::AudRenU(Core::System& system_)
: ServiceFramework{system_, "audren:u"},
: ServiceFramework{system_, "audren:u", ServiceThreadType::CreateNew},
service_context{system_, "audren:u"}, impl{std::make_unique<Manager>(system_)} {
// clang-format off
static const FunctionInfo functions[] = {
+1 -1
View File
@@ -97,7 +97,7 @@ void IUser::IsNfcEnabled(Kernel::HLERequestContext& ctx) {
}
void IUser::ListDevices(Kernel::HLERequestContext& ctx) {
LOG_INFO(Service_NFC, "called");
LOG_DEBUG(Service_NFC, "called");
if (state == State::NonInitialized) {
IPC::ResponseBuilder rb{ctx, 2};

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