Compare commits

...

600 Commits

Author SHA1 Message Date
Lioncash
aa44eb639b kernel/server_port: Make data members private
With this, all kernel objects finally have all of their data members
behind an interface, making it nicer to reason about interactions with
other code (as external code no longer has the freedom to totally alter
internals and potentially messing up invariants).
2019-03-11 10:41:05 -04:00
bunnei
0aa824b12f Merge pull request #2207 from lioncash/hwopus
service/audio/hwopus: Move decoder state to its own class
2019-03-10 17:32:39 -04:00
bunnei
037d9bdde3 Merge pull request #2193 from lioncash/global
kernel/scheduler: Pass in system instance in constructor
2019-03-10 17:29:01 -04:00
bunnei
633ce92908 Merge pull request #2147 from ReinUsesLisp/texture-clean
shader_ir: Remove "extras" from the MetaTexture
2019-03-10 17:28:36 -04:00
bunnei
4a84921b31 Merge pull request #2143 from ReinUsesLisp/texview
gl_rasterizer_cache: Create texture views for array discrepancies
2019-03-10 17:27:49 -04:00
bunnei
add8b1df68 Merge pull request #2220 from lioncash/cubeb
audio_core/cubeb_sink: Convert _MSC_VER ifdefs to _WIN32
2019-03-10 17:26:20 -04:00
Mat M
0ea2771889 Merge pull request #2217 from ReinUsesLisp/rasterizer-logger
gl_rasterizer: Minor logger changes
2019-03-10 03:16:00 -04:00
Mat M
9ae680c639 Merge pull request #2219 from Hexagon12/log-settings
core/settings: Log more setting values
2019-03-10 03:15:01 -04:00
Mat M
46fdf8c819 Merge pull request #2218 from ReinUsesLisp/cmd-cast
yuzu_cmd/config: Silent implicit cast warning
2019-03-10 03:14:34 -04:00
Lioncash
4a4e87e971 audio_core/cubeb_sink: Convert _MSC_VER ifdefs to _WIN32
This behavior also needs to be visible for MinGW builds as well.
2019-03-09 18:06:23 -05:00
Hexagon12
e6f652ae12 clang fix 2019-03-09 16:42:56 +02:00
Hexagon12
6ce8de4b5f Log 2 new setting values 2019-03-09 14:58:15 +02:00
ReinUsesLisp
45ef421b6b yuzu_cmd/config: Replace C casts with static_cast 2019-03-09 03:59:23 -03:00
ReinUsesLisp
fedef7bda3 yuzu_cmd/config: Silent implicit cast warning 2019-03-09 03:58:20 -03:00
ReinUsesLisp
6ee0ba64c8 gl_rasterizer: Minor logger changes 2019-03-09 03:34:49 -03:00
bunnei
9909d40530 Merge pull request #2210 from lioncash/optional
kernel/hle_ipc: Convert std::shared_ptr IPC header instances to std::optional
2019-03-08 16:35:57 -05:00
bunnei
160fc63c72 Merge pull request #2209 from lioncash/reorder
video_core/gpu_thread: Silence a -Wreorder warning
2019-03-08 12:04:26 -05:00
bunnei
78c803b4f3 Merge pull request #2208 from lioncash/gpu
video_core/gpu: Make GPU's destructor virtual
2019-03-08 12:03:58 -05:00
bunnei
1143923cdd Merge pull request #2191 from ReinUsesLisp/maxwell-to-vk
maxwell_to_vk: Initial implementation
2019-03-08 11:51:08 -05:00
bunnei
d10dffed44 Merge pull request #2212 from ReinUsesLisp/dma-push-fix
dma_pusher: Store command_list_header by copy
2019-03-08 11:48:32 -05:00
ReinUsesLisp
e7ac5a6adf dma_pusher: Store command_list_header by copy
Instead of holding a reference that will get invalidated by
dma_pushbuffer.pop(), hold it as a copy. This doesn't have any
performance cost since CommandListHeader is 8 bytes long.
2019-03-08 04:06:54 -03:00
Lioncash
fbb82e61e3 kernel/hle_ipc: Convert std::shared_ptr IPC header instances to std::optional
There's no real need to use a shared lifetime here, since we don't
actually expose them to anything else. This is also kind of an
unnecessary use of the heap given the objects themselves are so small;
small enough, in fact that changing over to optionals actually reduces
the overall size of the HLERequestContext struct (818 bytes to 808
bytes).
2019-03-07 23:34:37 -05:00
Lioncash
69749a88cd travis: Bump macOS version to 10.14
For whatever bizarre reason, Apple only made a few of std::optional's
member functions available on newer SDK versions. Given we can't even
run yuzu on macOS, and we keep the builder around to ensure that it
always at least compiles on macOS, we can bump this up a version.
2019-03-07 23:34:37 -05:00
bunnei
d26ee6e01e Merge pull request #2195 from lioncash/shared-global
kernel/shared_memory: Get rid of the use of global accessor functions within Create()
2019-03-07 17:26:11 -05:00
Lioncash
e99a148628 common/bit_field: Make BitField trivially copyable
This makes the class much more flexible and doesn't make performing
copies with classes that contain a bitfield member a pain.

Given BitField instances are only intended to be used within unions, the
fact the full storage value would be copied isn't a big concern (only
sizeof(union_type) would be copied anyways).

While we're at it, provide defaulted move constructors for consistency.
2019-03-07 17:05:44 -05:00
Lioncash
c2d4c8b95e video_core/gpu_thread: Remove unimplemented WaitForIdle function prototype
This function didn't have a definition, so we can remove it to prevent
accidentally attempting to use it.
2019-03-07 16:08:52 -05:00
Lioncash
48a461a629 video_core/gpu_thread: Amend constructor initializer list order
Moves the data members to satisfy the order they're declared as in the
constructor initializer list.

Silences a -Wreorder warning.
2019-03-07 16:05:49 -05:00
Lioncash
24e2e601d5 video_core/gpu: Make GPU's destructor virtual
Because of the recent separation of GPU functionality into sync/async
variants, we need to mark the destructor virtual to provide proper
destruction behavior, given we use the base class within the System
class.

Prior to this, it was undefined behavior whether or not the destructor
in the derived classes would ever execute.
2019-03-07 15:59:45 -05:00
bunnei
3b63a46ca4 Merge pull request #2196 from DarkLordZach/web-applet-esc
web_browser: Add shortcut to Enter key to exit applet
2019-03-07 15:32:32 -05:00
bunnei
c63a0e88b7 Merge pull request #2202 from lioncash/port-priv
kernel/client_session, kernel/server_session: Make data members private
2019-03-07 15:31:26 -05:00
bunnei
1a4d733ec7 Merge pull request #2205 from FearlessTobi/docked-undocked-hotkey
yuzu: add a hotkey to switch between undocked and docked mode
2019-03-07 11:33:24 -05:00
bunnei
d9e9e71aec Merge pull request #2206 from lioncash/audio-stop
service/audio/audout_u: Only actually stop the audio stream in StopAudioOut if the stream is playing
2019-03-07 10:47:59 -05:00
bunnei
4f352833a5 Merge pull request #2055 from bunnei/gpu-thread
Asynchronous GPU command processing
2019-03-07 10:41:53 -05:00
Lioncash
d03ae881fd service/audio/hwopus: Move decoder state to its own class
Moves the non-multistream specific state to its own class. This will be
necessary to support the multistream variants of opus decoding.
2019-03-07 07:47:09 -05:00
Lioncash
960057cba0 service/audio/hwopus: Provide a name for the second word of OpusPacketHeader
This indicates the entropy coder's final range.
2019-03-07 05:48:35 -05:00
Lioncash
d41d85766f service/audio/hwopus: Move Opus packet header out of the IHardwareOpusDecoderManager
This will be utilized by more than just that class in the future. This
also renames it from OpusHeader to OpusPacketHeader to be more specific
about what kind of header it is.
2019-03-07 05:37:08 -05:00
Lioncash
3293877456 service/audio/hwopus: Enclose internals in an anonymous namespace
Makes it impossible to violate the ODR, as well as providing a place for
future changes.
2019-03-07 05:32:42 -05:00
Lioncash
64e7524f36 service/audio/audout_u: Only actually stop the audio stream in StopAudioOut if the stream is playing
The service itself only does further actions if the stream is playing.
If the stream is already stopped, then it just exits successfully.
2019-03-07 03:39:01 -05:00
bunnei
076c76f4e4 Merge pull request #2149 from ReinUsesLisp/decoders-style
gl_rasterizer_cache: Move format conversion functions to their own file
2019-03-06 21:56:20 -05:00
bunnei
ed0bdcc638 Merge pull request #2197 from lioncash/include
core/hle/ipc: Remove unnecessary includes
2019-03-06 21:55:16 -05:00
bunnei
84ad81ee67 gpu_thread: Fix deadlock with threading idle state check. 2019-03-06 21:48:57 -05:00
bunnei
63aa08acbe gpu_thread: (HACK) Ignore flush on FlushAndInvalidateRegion. 2019-03-06 21:48:57 -05:00
bunnei
3f1b4fb23a gpu: Always flush. 2019-03-06 21:48:57 -05:00
bunnei
aaa373585c gpu: Refactor a/synchronous implementations into their own classes. 2019-03-06 21:48:57 -05:00
bunnei
7b574f406b gpu: Move command processing to another thread. 2019-03-06 21:48:57 -05:00
bunnei
65651078e5 bootmanager: Ensure that we have a context for shader loading. 2019-03-06 21:48:56 -05:00
bunnei
d2ff93c319 Merge pull request #2190 from lioncash/ogl-global
core: Remove the global telemetry accessor function
2019-03-06 21:41:53 -05:00
bunnei
ac51d048a9 gpu: Refactor command and swap buffers interface for asynch. 2019-03-06 21:09:09 -05:00
bunnei
4483089d70 gpu: Refactor to take RendererBase instead of RasterizerInterface. 2019-03-06 21:09:09 -05:00
bunnei
d6015ee211 settings: Add new graphics setting for use_asynchronous_gpu_emulation. 2019-03-06 21:09:09 -05:00
bunnei
81e086b5ac core: Set is_powered_on before GPU is initialized. 2019-03-06 21:07:33 -05:00
bunnei
75b417489a Merge pull request #2199 from lioncash/arbiter
kernel/address_arbiter: Convert the address arbiter into a class
2019-03-06 15:55:56 -05:00
bunnei
e9b05e86b9 Merge pull request #2201 from lioncash/audio-retval
hle/service/audio/audout_u: Correct lack of return in failure case of AppendAudioOutBufferImpl()
2019-03-06 14:20:04 -05:00
bunnei
8ee78521fa Merge pull request #2204 from lioncash/wait-tree
yuzu/debugger/wait_tree: Remove use of global CurrentProcess accessor
2019-03-06 14:17:34 -05:00
fearlessTobi
c8d6f0cb82 yuzu: add a hotkey to switch between undocked and docked mode 2019-03-06 19:31:23 +01:00
Lioncash
9ac176d5a3 hle/service/audio/audout_u: Correct lack of return in failure case of AppendAudioOutBufferImpl()
Previously we were overwriting the error case with a success code
further down (which is definitely not what we should be doing here).
2019-03-06 11:44:32 -05:00
bunnei
234f00bdd4 Merge pull request #2194 from lioncash/mem
svc: Move memory range checking functions to the VMManager class
2019-03-06 11:43:07 -05:00
bunnei
5a57b1a09b Merge pull request #2200 from lioncash/audio
hle/service/audio: Extract audio error codes to a header
2019-03-06 10:52:45 -05:00
bunnei
22f105c06d Merge pull request #2203 from lioncash/engines-include
video_core/engines: Remove unnecessary includes
2019-03-06 10:51:27 -05:00
bunnei
10f08ab9ec Merge pull request #2198 from lioncash/todo
{kernel/thread, video_core/surface}: Remove obsolete TODOs
2019-03-06 10:51:03 -05:00
Lioncash
196cc82913 yuzu/debugger/wait_tree: Remove use of global CurrentProcess accessor
We already have the thread instance that was created under the current
process, so we can just pass the handle table of it along to retrieve
the owner of the mutex.
2019-03-05 21:52:21 -05:00
Lioncash
f9ee0dc7ee video_core/engines: Remove unnecessary includes
Removes a few unnecessary dependencies on core-related machinery, such
as the core.h and memory.h, which reduces the amount of rebuilding
necessary if those files change.

This also uncovered some indirect dependencies within other source
files. This also fixes those.
2019-03-05 20:35:32 -05:00
Lioncash
221613d4ea kernel/server_session: Make data members private
Makes it much nicer to locally reason about server session behavior, as
part of its functionality isn't placed around other classes.
2019-03-05 20:10:07 -05:00
Lioncash
7526b6fce3 kernel/client_session: Make data members private
These can be made private, as they aren't accessed in contexts that
require them to be public.
2019-03-05 20:10:03 -05:00
Lioncash
ad9dbeb44b hle/service/audio: Extract audio error codes to a header
Places all error codes in an easily includable header.

This also corrects the unsupported error code (I accidentally used the
hex value when I meant to use the decimal one).
2019-03-05 16:51:37 -05:00
Lioncash
c161389a0f kernel/address_arbiter: Pass in system instance to constructor
Allows getting rid of reliance on the global accessor functions and
instead operating on the provided system instance.
2019-03-05 15:47:03 -05:00
Lioncash
9d9676f620 kernel/address_arbiter: Minor tidying up
- Invert conditions into guard clases where applicable.
- Mark std::vector parameter of WakeThreads as const
2019-03-05 12:58:31 -05:00
Lioncash
ec6664f6d6 kernel/address_arbiter: Convert the address arbiter into a class
Places all of the functions for address arbiter operation into a class.
This will be necessary for future deglobalizing efforts related to both
the memory and system itself.
2019-03-05 12:58:26 -05:00
Lioncash
42085ff110 video_core/surface: Remove obsolete TODO in PixelFormatFromRenderTargetFormat()
This isn't needed anymore, according to Hexagon
2019-03-05 10:15:06 -05:00
Lioncash
79f970e6de kernel/thread: Remove obsolete TODO in Create()
This is a TODO carried over from Citra that doesn't apply here.
2019-03-05 10:05:49 -05:00
Lioncash
02bc9e9de1 core/hle/ipc: Remove unnecessary includes
Removes a few inclusion dependencies from the headers or replaces
existing ones with ones that don't indirectly include the required
headers.

This allows removing an inclusion of core/memory.h, meaning that if the
memory header is ever changed in the future, it won't result in
rebuilding the entirety of the HLE services (as the IPC headers are used
quite ubiquitously throughout the HLE service implementations).
2019-03-05 09:53:38 -05:00
bunnei
cc92c054ec Merge pull request #2185 from FearlessTobi/port-4630
Port citra-emu/citra#4630: "Memory: don't lock hle mutex in memory read/write"
2019-03-04 18:44:53 -05:00
Zach Hilman
4130b07f88 web_browser: Add shortcut to Enter key to exit applet
Addresses issues where a user in fullscreen could not exit some web applets without leaving fullscreen.
2019-03-04 18:26:28 -05:00
Lioncash
40de7f6fe8 vm_manager: Use range helpers in HeapAlloc() and HeapFree()
Significantly tidies up two guard conditionals.
2019-03-04 17:16:52 -05:00
Lioncash
6c42a23550 vm_manager: Provide address range checking functions for other memory regions
Makes the interface uniform when it comes to checking various memory
regions.
2019-03-04 17:08:55 -05:00
Lioncash
fad20213e6 kernel/scheduler: Pass in system instance in constructor
Avoids directly relying on the global system instance and instead makes
an arbitrary system instance an explicit dependency on construction.

This also allows removing dependencies on some global accessor functions
as well.
2019-03-04 17:01:37 -05:00
Lioncash
f59040d752 kernel/shared_memory: Get rid of the use of global accessor functions within Create()
Given we already pass in a reference to the kernel that the shared
memory instance is created under, we can just use that to check the
current process, rather than using the global accessor functions.

This allows removing direct dependency on the system instance entirely.
2019-03-04 16:52:36 -05:00
Lioncash
0be8fffc99 svc: Migrate address range checking functions to VMManager
Provides a bit of a more proper interface for these functions.
2019-03-04 16:32:03 -05:00
bunnei
07e13d6728 Merge pull request #2165 from ReinUsesLisp/unbind-tex
gl_rasterizer: Unbind textures but don't apply the gl_state
2019-03-04 13:51:59 -05:00
bunnei
6ad66acce2 Merge pull request #2188 from lioncash/log-static
logging/backend: Move CreateEntry into the Impl class. Relocate local static to a class variable
2019-03-04 13:46:01 -05:00
Lioncash
b114928459 core/core: Remove the global telemetry accessor function
With all usages converted off of it, this function can be removed.
2019-03-04 10:24:13 -05:00
Lioncash
319365fdf0 yuzu: Remove usage of the global telemetry accessor
In these cases the system object is nearby, and in the other, the
long-form of accessing the telemetry instance is already used, so we can
get rid of the use of the global accessor.
2019-03-04 10:24:13 -05:00
Lioncash
697a4669e1 yuzu-cmd/yuzu: Replace direct usage of the global system telemetry accessor in main()
We already have the system instance around, so we can use that instead
of the accessor.
2019-03-04 10:24:13 -05:00
Lioncash
b5f0dc95db core/core: Replace direct usage of the global system telemetry accessor from Shutdown()
The telemetry instance is actually a member of the class itself, so we
can access it directly instead of going through the global accessor.
2019-03-04 10:24:13 -05:00
Lioncash
90febaf717 video_core/renderer_opengl: Replace direct usage of global system object accessors
We already pass a reference to the system object to the constructor of the renderer,
so we can just use that instead of using the global accessor functions.
2019-03-04 10:24:09 -05:00
ReinUsesLisp
1f6571b3de maxwell_to_vk: Initial implementation 2019-03-04 04:06:05 -03:00
bunnei
be6bf37224 Merge pull request #2189 from lioncash/web
web_service: Remove unnecessary inclusions
2019-03-03 22:56:49 -05:00
Lioncash
aa30fd75cd web_service: Remove unnecessary inclusions
Reduces the potential amount of rebuilding necessary if any headers
change. In particular, we were including a header from the core library
when we don't even link the core library to the web_service library, so
this also gets rid of an indirect dependency.
2019-03-02 14:58:49 -05:00
Mat M
169d19f7b9 Merge pull request #2154 from FearlessTobi/port-4647
Port citra-emu/citra#4647: "citra_qt/main: make SPEED_LIMIT_STEP static constexpr"
2019-03-02 14:46:04 -05:00
Lioncash
f8f1ff0b4f logging/backend: Make time_origin a class variable instead of a local static
Moves local global state into the Impl class itself and initializes it
at the creation of the instance instead of in the function.

This makes it nicer for weakly-ordered architectures, given the
CreateEntry() class won't need to have atomic loads executed for each
individual call to the CreateEntry class.
2019-03-02 14:44:24 -05:00
Lioncash
43c1092031 logging/backend: Move CreateEntry into the Impl class
This function is only ever used within this source file and makes it
easier to remove static state in the following change.
2019-03-02 14:44:24 -05:00
Mat M
a461e266ea Merge pull request #2183 from ReinUsesLisp/vk-buffer-cache-clang
vk_buffer_cache: Fix clang-format
2019-03-02 14:43:15 -05:00
James Rowe
2e2f6aa71a Merge pull request #2186 from honzapatCZ/patch-1
Yuzu can render 3D.
2019-03-02 10:10:01 -07:00
fearlessTobi
71c30a0a89 citra_qt/main: make SPEED_LIMIT_STEP static constexpr
MSVC does not seem to like using constexpr values in a lambda that were declared outside of it.
Previously on MSVC build the hotkeys to inc-/decrease the speed limit were not working correctly because in the lambda the SPEED_LIMIT_STEP had garbage values.
After googling around a bit I found: https://github.com/codeplaysoftware/computecpp-sdk/issues/95 which seems to be a similar issue.
Trying the suggested fix to make the variable static constexpr also fixes the bug here.
2019-03-02 17:43:19 +01:00
Nejcraft
90fd257b47 Yuzu can render 3D.
Yuzu can now render 3D graphics to some degree.
2019-03-02 17:23:05 +01:00
Weiyi Wang
5159f4eee8 Memory: don't lock hle mutex in memory read/write
The comment already invalidates itself: neither MMIO nor rasterizer cache belongsHLE kernel state. This mutex has a too large scope if MMIO or cache is included, which is prone to dead lock when multiple thread acquires these resource at the same time. If necessary, each MMIO component or rasterizer should have their own lock.
2019-03-02 15:20:05 +01:00
bunnei
3c39b39bbc Merge pull request #2182 from bunnei/my-wasted-friday
fuck git for ruining my day, I will learn but I will not forgive
2019-03-02 00:57:15 -05:00
ReinUsesLisp
8e84e81e74 vk_buffer_cache: Fix clang-format 2019-03-02 02:16:45 -03:00
bunnei
e22670fbc3 Merge pull request #2178 from ReinUsesLisp/vk-buffer-cache
vk_buffer_cache: Implement a buffer cache
2019-03-02 00:13:33 -05:00
bunnei
ab70c2583d fuck git for ruining my day, I will learn but I will not forgive 2019-03-02 00:01:34 -05:00
ReinUsesLisp
35c105a108 vk_buffer_cache: Implement a buffer cache
This buffer cache is just like OpenGL's buffer cache with some minor
style changes. It uses VKStreamBuffer.
2019-03-01 17:33:36 -03:00
bunnei
1da8a0c2a8 Merge pull request #2173 from lioncash/capture
yuzu/compatdb: Remove unused lambda capture
2019-03-01 09:55:35 -05:00
bunnei
12e74fe801 Merge pull request #2180 from lioncash/audren
service/audio: Provide an implementation of ExecuteAudioRendererRendering
2019-03-01 09:50:14 -05:00
bunnei
115fc6120c Merge pull request #2181 from lioncash/audren2
service/audio/audren_u: Implement OpenAudioRendererAuto
2019-03-01 09:49:23 -05:00
Lioncash
84aff56644 service/audio/audren_u: Implement OpenAudioRendererAuto
This currently has the same behavior as the regular
OpenAudioRenderer API function, so we can just move the code within
OpenAudioRenderer to an internal function that both service functions
call.
2019-03-01 05:40:29 -05:00
Lioncash
42dc73157c service/audio: Provide an implementation of ExecuteAudioRendererRendering
This service function appears to do nothing noteworthy on the switch.
All it does at the moment is either return an error code or abort the
system. Given we obviously don't want to kill the system, we just opt
for always returning the error code.
2019-03-01 03:37:00 -05:00
ReinUsesLisp
e85066dac7 gl_rasterizer: Remove texture unbinding after dispatching a draw call
Unbinding was required when OpenGL delete operations didn't unbind a
resource if it was bound. This is no longer needed and can be removed.
2019-02-28 00:17:50 -03:00
ReinUsesLisp
bb3ab7d66c gl_state: Fixup multibind bug 2019-02-28 00:17:03 -03:00
bunnei
49c6d21b31 Merge pull request #2174 from lioncash/fwd
service/hid: Amend forward declaration of ServiceManager
2019-02-27 21:20:06 -05:00
bunnei
1b13859af8 Merge pull request #2152 from ReinUsesLisp/vk-stream-buffer
vk_stream_buffer: Implement a stream buffer
2019-02-27 21:19:15 -05:00
bunnei
1f5d6a8fed Merge pull request #2121 from FernandoS27/texception2
Improve the Accuracy of the Rasterizer Cache through a Texception Pass
2019-02-27 21:17:55 -05:00
bunnei
66f4fd4c81 Merge pull request #2172 from lioncash/reorder
gl_rasterizer/vk_memory_manager: Silence -Wreorder warnings
2019-02-27 21:14:20 -05:00
Fernando Sahmkow
7ea097e5c2 Devirtualize Register/Unregister and use a wrapper instead. 2019-02-27 21:58:50 -04:00
Fernando Sahmkow
5a9204dbd7 Corrections and redesign. 2019-02-27 21:58:49 -04:00
Fernando Sahmkow
d6b9b51606 Fix linux compile error. 2019-02-27 21:58:48 -04:00
Fernando Sahmkow
e64fa4d2ea Remove NotifyFrameBuffer as we are doing a texception pass every drawcall. 2019-02-27 21:58:47 -04:00
Fernando Sahmkow
3558c88442 Remove certain optimizations that caused texception to fail in certain scenarios. 2019-02-27 21:58:45 -04:00
Fernando Sahmkow
e9d84ef22c Bug fixes and formatting 2019-02-27 21:58:44 -04:00
Fernando Sahmkow
5bc82d124c rasterizer_cache_gl: Implement Texception Pass 2019-02-27 21:58:43 -04:00
Fernando Sahmkow
8932001610 rasterizer_cache_gl: Implement Partial Reinterpretation of Surfaces. 2019-02-27 21:58:40 -04:00
Fernando Sahmkow
44ea2810e4 rasterizer_cache: mark reinterpreted surfaces and add ability to reload marked surfaces on next use. 2019-02-27 21:58:39 -04:00
Fernando Sahmkow
d583fc1e97 rasterizer_cache_gl: Notify on framebuffer change 2019-02-27 21:58:37 -04:00
Fernando Sahmkow
45b6d2d349 rasterizer_cache: Expose FlushObject to Child classes and allow redefining of Register and Unregister 2019-02-27 21:57:33 -04:00
bunnei
f15e2dd881 Merge pull request #2163 from ReinUsesLisp/bitset-dirty
maxwell_3d: Use std::bitset to manage dirty flags
2019-02-27 20:50:08 -05:00
Annomatg
ef84c70d22 Speed up memory page mapping (#2141)
- Memory::MapPages total samplecount was reduced from 4.6% to 1.06%.
- From main menu into the game from 1.03% to 0.35%
2019-02-27 17:22:47 -05:00
bunnei
532dda0499 Merge pull request #2176 from lioncash/com
audio_core/cubeb_sink: Ensure COM is initialized on Windows prior to calling cubeb_init
2019-02-27 17:12:06 -05:00
Lioncash
1068c1b06f audio_core/cubeb_sink: Ensure COM is initialized on Windows prior to calling cubeb_init
cubeb now requires that COM explicitly be initialized on the thread
prior to calling cubeb_init.
2019-02-27 16:14:53 -05:00
ReinUsesLisp
27ddbeb01c gl_rasterizer_cache: Create texture views for array discrepancies
When a texture is sampled in a shader with a different array mode than
the cached state, create a texture view and bind that to the shader
instead.
2019-02-27 14:41:06 -03:00
Lioncash
6335bf136f service/hid: Amend forward declaration of ServiceManager
The SM namespace is within the Service namespace, so this was forward
declaring a type that didn't exist.
2019-02-27 11:36:48 -05:00
Lioncash
456c7043bd yuzu/compatdb: Remove unused lambda capture
Silences a compiler warning with clang.
2019-02-27 11:30:36 -05:00
bunnei
42f7c11021 Merge pull request #2169 from lioncash/naming
audio_core/audio_renderer: Provide names for some parameters of AudioRendererParameter
2019-02-27 11:26:54 -05:00
bunnei
14430f7df9 Merge pull request #2170 from lioncash/emu-window
core/frontend/emu_window: Make ClipToTouchScreen a const member function
2019-02-27 11:26:24 -05:00
bunnei
eb5a3dd1c7 Merge pull request #2161 from lioncash/handle-table
kernel/handle_table: Allow process capabilities to limit the handle table size
2019-02-27 11:22:26 -05:00
bunnei
be1a1584fc Merge pull request #2168 from lioncash/cubeb
externals: Update cubeb to the master version
2019-02-27 11:20:14 -05:00
bunnei
66e023fba2 Merge pull request #2167 from lioncash/namespace
common: Move Quaternion, Rectangle, Vec2, Vec3, and Vec4 into the Common namespace
2019-02-27 11:19:53 -05:00
bunnei
b27e6ad912 Merge pull request #2171 from lioncash/pragma
gl_shader_disk_cache: Remove #pragma once from cpp file
2019-02-27 11:19:17 -05:00
Lioncash
16ea93c11e vk_memory_manager: Reorder constructor initializer list in terms of member declaration order
Reorders members in the order that they would actually be initialized
in. Silences a -Wreorder warning.
2019-02-27 11:08:19 -05:00
Lioncash
a6a783b3dc gl_rasterizer: Reorder constructor initializer list in terms of member declaration order
Orders the members in the order they would actually be initialized in.
Silences a -Wreorder warning.
2019-02-27 11:08:19 -05:00
Lioncash
e7eff72e83 gl_shader_disk_cache: Remove #pragma once from cpp file
This is only necessary in headers. Silences a warning with clang.
2019-02-27 11:02:49 -05:00
Lioncash
46b3209abb core/frontend/emu_window: Make ClipToTouchScreen a const member function
This member function doesn't modify instance state, so it can have the
const specifier applied to it.
2019-02-27 08:54:42 -05:00
Lioncash
0e1b5acc6a audio_core/audio_renderer: Name previously unknown parameters of AudioRendererParameter
Provides names for previously unknown entries (aside from the two u8
that appear to be padding bytes, and a single word that also appears
to be reserved or padding).

This will be useful in subsequent changes when unstubbing behavior related
to the audio renderer services.
2019-02-27 06:09:07 -05:00
Lioncash
b9238edd0d common/math_util: Move contents into the Common namespace
These types are within the common library, so they should be within the
Common namespace.
2019-02-27 03:38:39 -05:00
Lioncash
e56f32a071 externals: Update cubeb to 6f2420de8f155b10330cf973900ac7bdbfee589d
Keeps the audio library we use up to date.
2019-02-27 01:21:51 -05:00
Lioncash
1b855efd5e common/vector_math: Move Vec[x] types into the Common namespace
These types are within the common library, so they should be using the
Common namespace.
2019-02-26 22:38:36 -05:00
Lioncash
a1574aabd5 common/quaternion: Move Quaternion into the Common namespace
Quaternion is within the common library, so it should be using the
Common namespace.
2019-02-26 22:31:17 -05:00
ReinUsesLisp
0ad3c031f4 gl_rasterizer_cache: Move format conversion to its own file 2019-02-26 20:08:27 -03:00
ReinUsesLisp
0ccd490fcd decoders: Minor style changes 2019-02-26 20:08:27 -03:00
bunnei
10d1d58390 Merge pull request #2164 from ReinUsesLisp/configure-blit
renderer_opengl: Update pixel format tracking
2019-02-26 12:12:10 -05:00
ReinUsesLisp
d91e35a50a renderer_opengl: Update pixel format tracking 2019-02-26 03:47:16 -03:00
ReinUsesLisp
5219edd715 maxwell_3d: Use std::bitset to manage dirty flags 2019-02-26 03:01:48 -03:00
ReinUsesLisp
730eb1dad7 vk_stream_buffer: Remove copy code path 2019-02-26 02:09:43 -03:00
ReinUsesLisp
5ca63d0675 shader/decode: Remove extras from MetaTexture 2019-02-26 00:11:30 -03:00
ReinUsesLisp
48e6f77c03 shader/decode: Split memory and texture instructions decoding 2019-02-26 00:11:30 -03:00
bunnei
c3471bf618 Merge pull request #2156 from FreddyFunk/patch-1
file_sys/vfs_vector: Fix ignored offset on Write
2019-02-25 18:28:58 -05:00
bunnei
da1b45de34 Merge pull request #2158 from lioncash/table
service/vi: Update IManagerDisplayService's function table
2019-02-25 18:27:43 -05:00
bunnei
1cffd3848b Merge pull request #2160 from lioncash/audio-warn
audio_core: Resolve compilation warnings
2019-02-25 18:25:36 -05:00
bunnei
93c1630570 Merge pull request #2159 from lioncash/warn
shader/track: Resolve variable shadowing warnings
2019-02-25 13:26:00 -05:00
Lioncash
d29f9e9709 kernel/handle_table: Make local variables as const where applicable
Makes immutable state explicit.
2019-02-25 11:12:38 -05:00
Lioncash
5167d1577d kernel/handle_table: Allow process capabilities to limit the handle table size
The kernel allows restricting the total size of the handle table through
the process capability descriptors. Until now, this functionality wasn't
hooked up. With this, the process handle tables become properly restricted.

In the case of metadata-less executables, the handle table will assume
the maximum size is requested, preserving the behavior that existed
before these changes.
2019-02-25 11:12:32 -05:00
Lioncash
4f8cd74061 kernel/handle-table: In-class initialize data members
Directly initializes members where applicable.
2019-02-25 10:14:05 -05:00
Lioncash
0220862ba5 kernel/handle_table: Resolve truncation warnings
Avoids implicit truncation warnings from u32 -> u16 (the truncation is
desirable behavior here).
2019-02-25 09:53:21 -05:00
Lioncash
04d7b7e09d audio_core/cubeb_sink: Initialize CubebSinkStream's last_frame data member
Ensures that all member variables are initialized in a deterministic
manner across the board.
2019-02-25 09:40:37 -05:00
Lioncash
8250f9bb1c audio_core/cubeb_sink: Add override specifier to destructor
CubebSinkStream inherits from a base class with a virtual destructor, so
override can be appended to CubebSinkStream's destructor.
2019-02-25 09:38:27 -05:00
Lioncash
7cdeec20ec audio_core/cubeb_sink: Resolve variable shadowing warnings in SamplesInQueue
The name of the parameter was shadowing the member variable of the same
name. Instead, alter the name of the parameter to prevent said
shadowing.
2019-02-25 09:28:51 -05:00
Lioncash
a12f4efa2f audio_core/codec: Resolve truncation warnings within DecodeADPCM
The assignments here were performing an implicit truncation from int to
s16. Make it explicit that this is desired behavior.
2019-02-25 09:24:39 -05:00
Lioncash
c1b2e35625 shader/track: Resolve variable shadowing warnings 2019-02-25 09:10:59 -05:00
Lioncash
be7dad5e7e service/vi: Update IManagerDisplayService's function table
Amends it to add the 7.0.0+ CreateStrayLayer function.
2019-02-25 08:09:00 -05:00
bunnei
c07987dfab Merge pull request #2118 from FernandoS27/ipa-improve
shader_decompiler: Improve Accuracy of Attribute Interpolation.
2019-02-24 23:04:22 -05:00
bunnei
c4243c07cc Merge pull request #2119 from FernandoS27/fix-copy
rasterizer_cache_gl: Only do fast layered copy on the same format.
2019-02-24 23:03:52 -05:00
bunnei
c6170565b5 Merge pull request #2155 from FearlessTobi/port-4655
Port citra-emu/citra#4655: "Remove GCC version checks"
2019-02-24 23:03:13 -05:00
bunnei
57985fb16a Merge pull request #2144 from lioncash/factor
service/vi: Convert Display and Layer structs into classes
2019-02-24 23:02:50 -05:00
Frederic L
517933adcb file_sys/vfs_vector: Fix ignored offset on Write 2019-02-25 00:27:49 +01:00
tgsm
030814b1cb Remove GCC version checks
Citra can't be compiled using GCC <7 because of required C++17 support, so these version checks don't need to exist anymore.
2019-02-24 15:24:06 +01:00
bunnei
90c780e6f3 Merge pull request #2139 from degasus/dma_pusher
video_core/dma_pusher: The full list of headers at once.
2019-02-24 04:15:49 -05:00
ReinUsesLisp
33a0597603 vk_stream_buffer: Implement a stream buffer
This manages two kinds of streaming buffers: one for unified memory
models and one for dedicated GPUs. The first one skips the copy from the
staging buffer to the real buffer, since it creates an unified buffer.

This implementation waits for all fences to finish their operation
before "invalidating". This is suboptimal since it should allocate
another buffer or start searching from the beginning. There is room for
improvement here.

This could also handle AMD's "pinned" memory (a heap with 256 MiB) that
seems to be designed for buffer streaming.
2019-02-24 04:27:51 -03:00
ReinUsesLisp
281a8bf259 vk_resource_manager: Minor VKFenceWatch changes 2019-02-24 04:19:04 -03:00
bunnei
f7090bacc5 Merge pull request #2146 from ReinUsesLisp/vulkan-scheduler
vk_scheduler: Implement a scheduler
2019-02-23 23:32:43 -05:00
bunnei
d062991643 Merge pull request #2150 from ReinUsesLisp/fixup-layer-swizzle
gl_rasterizer_cache: Fixup parameter order in layered swizzle
2019-02-23 23:31:34 -05:00
bunnei
4ab978d670 Merge pull request #2151 from ReinUsesLisp/fixup-vk-memory-manager
vk_memory_manager: Fixup commit interval allocation
2019-02-23 23:29:53 -05:00
ReinUsesLisp
92050c4d86 vk_memory_manager: Fixup commit interval allocation
VKMemoryCommitImpl was using as the end of its interval "begin + end".
That ended up wasting memory.
2019-02-24 01:04:41 -03:00
ReinUsesLisp
abef11a540 gl_rasterizer_cache: Fixup parameter order in layered swizzle 2019-02-23 23:27:30 -03:00
ReinUsesLisp
f546fb35ed vk_scheduler: Implement a scheduler
The scheduler abstracts command buffer and fence management with an
interface that's able to do OpenGL-like operations on Vulkan command
buffers.

It returns by value a command buffer and fence that have to be used for
subsequent operations until Flush or Finish is executed, after that the
current execution context (the pair of command buffers and fences) gets
invalidated a new one must be fetched. Thankfully validation layers will
quickly detect if this is skipped throwing an error due to modifications
to a sent command buffer.
2019-02-22 01:33:32 -03:00
bunnei
94b27bb8a5 Merge pull request #2138 from ReinUsesLisp/vulkan-memory-manager
vk_memory_manager: Implement memory manager
2019-02-21 22:26:54 -05:00
Lioncash
90528f1326 service/nvflinger: Store BufferQueue instances as regular data members
The NVFlinger service is already passed into services that need to
guarantee its lifetime, so the BufferQueue instances will already live
as long as they're needed. Making them std::shared_ptr instances in this
case is unnecessary.
2019-02-21 22:09:46 -05:00
Lioncash
fd15730767 service/vi/vi_layer: Convert Layer struct into a class
Like the previous changes made to the Display struct, this prepares the
Layer struct for changes to its interface. Given Layer will be given
more invariants in the future, we convert it into a class to better
signify that.
2019-02-21 12:13:09 -05:00
Lioncash
fa4dc2cf42 service/nvflinger: Move display specifics over to vi_display
With the display and layer structures relocated to the vi service, we
can begin giving these a proper interface before beginning to properly
support the display types.

This converts the display struct into a class and provides it with the
necessary functions to preserve behavior within the NVFlinger class.
2019-02-21 12:13:04 -05:00
bunnei
9539c4203b Merge pull request #2125 from ReinUsesLisp/fixup-glstate
gl_state: Synchronize gl_state even when state is disabled
2019-02-20 21:47:46 -05:00
bunnei
ae437320c8 Merge pull request #2130 from lioncash/system_engine
video_core: Remove usages of System::GetInstance() within the engines
2019-02-20 21:24:56 -05:00
Jungy
3273f93cd5 Fixes Unicode Key File Directories (#2120)
* Fixes Unicode Key File Directories

Adds code so that when loading a file it converts to UTF16 first, to
ensure the files can be opened. Code borrowed from FileUtil::Exists.

* Update src/core/crypto/key_manager.cpp

Co-Authored-By: Jungorend <Jungorend@users.noreply.github.com>

* Update src/core/crypto/key_manager.cpp

Co-Authored-By: Jungorend <Jungorend@users.noreply.github.com>

* Using FileUtil instead to be cleaner.

* Update src/core/crypto/key_manager.cpp

Co-Authored-By: Jungorend <Jungorend@users.noreply.github.com>
2019-02-20 21:24:25 -05:00
bunnei
ef559f5741 Merge pull request #2142 from lioncash/relocate
service/nvflinger: Relocate definitions of Layer and Display to the vi service
2019-02-20 21:21:55 -05:00
Lioncash
8d5d369b54 service/nvflinger: Relocate definitions of Layer and Display to the vi service
These are more closely related to the vi service as opposed to the
intermediary nvflinger.

This also places them in their relevant subfolder, as future changes to
these will likely result in subclassing to represent various displays
and services, as they're done within the service itself on hardware.

The reasoning for prefixing the display and layer source files is to
avoid potential clashing if two files with the same name are compiled
(e.g. if 'display.cpp/.h' or 'layer.cpp/.h' is added to another service
at any point), which MSVC will actually warn against. This prevents that
case from occurring.

This also presently coverts the std::array introduced within
f45c25aaba back to a std::vector to allow
the forward declaration of the Display type. Forward declaring a type
within a std::vector is allowed since the introduction of N4510
(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4510.html) by
Zhihao Yuan.
2019-02-19 18:27:16 -05:00
Markus Wick
6dd40976d0 video_core/dma_pusher: Simplyfy Step() logic.
As fetching command list headers and and the list of command headers is a fixed 1:1 relation now, they can be implemented within a single call.
This cleans up the Step() logic quite a bit.
2019-02-19 10:28:42 +01:00
Markus Wick
717394c980 video_core/dma_pusher: The full list of headers at once.
Fetching every u32 from memory leads to a big overhead. So let's fetch all of them as a block if possible.
This reduces the Memory::* calls by the dma_pusher by a factor of 10.
2019-02-19 09:58:38 +01:00
ReinUsesLisp
b675c97cdd vk_memory_manager: Implement memory manager
A memory manager object handles the memory allocations for a device. It
allocates chunks of Vulkan memory objects and then suballocates.
2019-02-19 03:42:28 -03:00
bunnei
4bce08d497 Merge pull request #2122 from ReinUsesLisp/vulkan-resource-manager
vk_resource_manager: Implement fence and command buffer allocator
2019-02-18 21:05:28 -05:00
bunnei
2bb02a0b78 Merge pull request #2134 from lioncash/naming
audio_core/buffer: Make const and non-const getter for samples consistent
2019-02-17 11:26:33 -05:00
bunnei
e869c5ef1a Merge pull request #2133 from lioncash/arbiter
address_arbiter: Use nested namespaces where applicable
2019-02-16 15:37:21 -05:00
bunnei
4699fdca8f Merge pull request #2127 from FearlessTobi/fix-screenshot-srgb
renderer_opengl: respect the sRGB colorspace for the screenshot feature
2019-02-16 15:36:00 -05:00
bunnei
cd7e1183e2 Merge pull request #2128 from FearlessTobi/port-4197
Port citra-emu/citra#4197: "threadsafe_queue: Add PopWait and use it where possible "
2019-02-16 15:34:49 -05:00
Lioncash
b009bda67a audio_core/buffer: Make const and non-const getter for samples consistent
This way proper const/non-const selection can occur.
2019-02-16 15:21:35 -05:00
Lioncash
0113c36300 address_arbiter: Use nested namespaces where applicable
A fairly trivial change. Other sections of the codebase use nested
namespaces instead of separate namespaces here. This one must have just
been overlooked.
2019-02-16 12:41:30 -05:00
Lioncash
a8fa5019b5 video_core: Remove usages of System::GetInstance() within the engines
Avoids the use of the global accessor in favor of explicitly making the
system a dependency within the interface.
2019-02-15 22:06:23 -05:00
James Rowe
99da6362c4 Merge pull request #2123 from lioncash/coretiming-global
core_timing: De-globalize core_timing facilities
2019-02-15 19:52:11 -07:00
Lioncash
bd983414f6 core_timing: Convert core timing into a class
Gets rid of the largest set of mutable global state within the core.
This also paves a way for eliminating usages of GetInstance() on the
System class as a follow-up.

Note that no behavioral changes have been made, and this simply extracts
the functionality into a class. This also has the benefit of making
dependencies on the core timing functionality explicit within the
relevant interfaces.
2019-02-15 21:50:25 -05:00
B3n30
2195f10d15 Adressed review comments 2019-02-15 22:14:54 +01:00
B3n30
4154936568 threadsafe_queue: Add WaitIfEmpty and use it in logging 2019-02-15 22:12:54 +01:00
fearlessTobi
9a56b99fa4 renderer_opengl: respect the sRGB colorspace for the screenshot feature
Previously, we were completely ignoring for screenshots whether the game uses RGB or sRGB.
This resulted in screenshot colors that looked off for some titles.
2019-02-15 21:27:29 +01:00
ReinUsesLisp
8dfc81239f gl_state: Synchronize gl_state even when state is disabled
There are some potential edge cases where gl_state may fail to track the
state if a related state changes while the toggle is disabled or it
didn't change. This addresses that.
2019-02-15 01:30:14 -03:00
bunnei
4327f430f1 Merge pull request #2112 from lioncash/shadowing
gl_rasterizer_cache: Get rid of variable shadowing
2019-02-14 21:45:20 -05:00
bunnei
a8fc5d6edd Merge pull request #2111 from ReinUsesLisp/fetch-fix
gl_shader_decompiler: Re-implement TLDS lod
2019-02-14 21:42:34 -05:00
ReinUsesLisp
ae6c052ed9 vk_resource_manager: Implement a command buffer pool with VKFencedPool 2019-02-14 18:44:26 -03:00
ReinUsesLisp
a2b6de7e9f vk_resource_manager: Add VKFencedPool interface
Handles a pool of resources protected by fences. Manages resource
overflow allocating more resources.

This class is intended to be used through inheritance.
2019-02-14 18:44:26 -03:00
ReinUsesLisp
0ffdd0a683 vk_resource_manager: Implement VKResourceManager and fence allocator
CommitFence iterates a pool of fences until one is found. If all fences
are being used at the same time, allocate more.
2019-02-14 18:44:26 -03:00
ReinUsesLisp
aa0b6babda vk_resource_manager: Implement VKFenceWatch
A fence watch is used to keep track of the usage of a fence and protect
a resource or set of resources without having to inherit from their
handlers.
2019-02-14 18:44:26 -03:00
ReinUsesLisp
25c2fe1c6b vk_resource_manager: Implement VKFence
Fences take ownership of objects, protecting them from GPU-side or
driver-side concurrent access. They must be commited from the resource
manager. Their usage flow is: commit the fence from the resource
manager, protect resources with it and use them, send the fence to an
execution queue and Wait for it if needed and then call Release. Used
resources will automatically be signaled when they are free to be
reused.
2019-02-14 18:44:26 -03:00
ReinUsesLisp
33a4cebc22 vk_resource_manager: Add VKResource interface
VKResource is an interface that gets signaled by a fence when it is free
to be reused.
2019-02-14 18:36:15 -03:00
bunnei
fcc3aa0bbf Merge pull request #2113 from ReinUsesLisp/vulkan-base
vulkan: Add dependencies and device abstraction
2019-02-14 10:06:48 -05:00
Fernando Sahmkow
10682ad7e0 shader_decompiler: Improve Accuracy of Attribute Interpolation. 2019-02-14 03:25:07 -04:00
bunnei
8490e7746a Merge pull request #2115 from lioncash/local
core_timing: Make EmptyTimedCallback a local variable
2019-02-13 21:42:04 -05:00
bunnei
f0c4ac9abd Merge pull request #2116 from lioncash/size
threadsafe_queue: Remove NeedSize template parameter
2019-02-13 21:41:25 -05:00
Fernando Sahmkow
bb41683394 rasterizer_cache_gl: Only do fast layered copy on the same format. As
glCopyImageSubData does not support different formats.
2019-02-13 16:55:00 -04:00
Lioncash
0829ef97ca threadsafe_queue: Use std::size_t for representing size
Makes it consistent with the regular standard containers in terms of
size representation. This also gets rid of dependence on our own
type aliases, removing the need for an include.
2019-02-12 22:39:53 -05:00
Lioncash
f0bfb24c61 threadsafe_queue: Remove NeedSize template parameter
The necessity of this parameter is dubious at best, and in 2019 probably
offers completely negligible savings as opposed to just leaving this
enabled. This removes it and simplifies the overall interface.
2019-02-12 22:09:51 -05:00
Lioncash
83ba3515ec core_timing: Make EmptyTimedCallback a local variable
Given this is only used in one place, it can be moved closest to its
usage site.
2019-02-12 21:47:18 -05:00
bunnei
cd542d5aac Merge pull request #2099 from greggameplayer/BGRA8-Framebuffer-Real
Implement BGRA8 framebuffer format
2019-02-12 21:44:20 -05:00
bunnei
c425a1a857 Merge pull request #2114 from lioncash/global
renderer_opengl: Remove reference to global system instance
2019-02-12 21:40:31 -05:00
ReinUsesLisp
8beca060d1 vk_device: Abstract device handling into a class
VKDevice contains all the data required to manage and initialize a
physical device. Its intention is to be passed across Vulkan objects to
query device-specific data (for example the logical device and the
dispatch loader).
2019-02-12 21:43:02 -03:00
Lioncash
86b55cb6df renderer_opengl: Remove reference to global system instance
We already store a reference to the system instance that the renderer is
created with, so we don't need to refer to the system instance via
Core::System::GetInstance()
2019-02-12 19:33:22 -05:00
bunnei
8135f4bfce Merge pull request #2110 from lioncash/namespace
core_timing: Rename CoreTiming namespace to Core::Timing
2019-02-12 19:26:37 -05:00
bunnei
c440ecfafe Merge pull request #2104 from ReinUsesLisp/compute-assert
kepler_compute: Fixup assert and rename the engine
2019-02-12 19:24:34 -05:00
Lioncash
054e39647c gl_rasterizer_cache: Remove unnecessary newline 2019-02-12 16:56:19 -05:00
Lioncash
e25c464c02 gl_rasterizer_cache: Get rid of variable shadowing
Avoids shadowing the members of the struct itself, which results in a
-Wshadow warning.
2019-02-12 16:46:39 -05:00
ReinUsesLisp
18fe910957 renderer_vulkan: Add declarations file
This file is intended to be included instead of vulkan/vulkan.hpp. It
includes declarations of unique handlers using a dynamic dispatcher
instead of a static one (which would require linking to a Vulkan
library).
2019-02-12 18:33:02 -03:00
ReinUsesLisp
b12ab4d805 logging: Add Vulkan backend logging class type 2019-02-12 18:33:02 -03:00
ReinUsesLisp
cc94a6d101 cmake: Add Vulkan option 2019-02-12 18:33:02 -03:00
ReinUsesLisp
afb8af9853 gitmodules: Add Vulkan headers dependency 2019-02-12 18:33:02 -03:00
ReinUsesLisp
e60d4d70bc gl_shader_decompiler: Re-implement TLDS lod 2019-02-12 17:03:07 -03:00
Lioncash
48d9d66dc5 core_timing: Rename CoreTiming namespace to Core::Timing
Places all of the timing-related functionality under the existing Core
namespace to keep things consistent, rather than having the timing
utilities sitting in its own completely separate namespace.
2019-02-12 12:42:17 -05:00
bunnei
444231a83d Merge pull request #2108 from FernandoS27/fix-cc
Fix incorrect value for CC bit in IADD
2019-02-12 10:39:03 -05:00
bunnei
c1accfefde Merge pull request #2109 from FernandoS27/fix-f2i
Corrected F2I None mode to RoundEven.
2019-02-12 10:20:29 -05:00
bunnei
27e5efd265 Merge pull request #2068 from ReinUsesLisp/shader-cleanup-textures
shader_ir: Clean texture management code
2019-02-12 10:20:15 -05:00
Fernando Sahmkow
f5ec165e8c Corrected F2I None mode to RoundEven. 2019-02-11 18:46:45 -04:00
Fernando Sahmkow
edd668047c Fix incorrect value for CC bit in IADD 2019-02-11 16:44:43 -04:00
ReinUsesLisp
1ddcd0e6f0 kepler_compute: Fixup assert and rename engines
When I originally added the compute assert I used the wrong
documentation. This addresses that.

The dispatch register was tested with homebrew against hardware and is
triggered by some games (e.g. Super Mario Odyssey). What exactly is
missing to get a valid program bound by this engine requires more
investigation.
2019-02-10 19:29:33 -03:00
greggameplayer
a6a73d8892 Implement BGRA8 framebuffer format 2019-02-09 23:44:01 +01:00
bunnei
1d98027a0e Merge pull request #1904 from bunnei/better-fermi-copy
gl_rasterizer: Implement a more accurate fermi 2D copy.
2019-02-08 23:32:24 -05:00
bunnei
2374471a1e Merge pull request #2096 from FearlessTobi/patch-3
nvdisp_disp0: change drawing message log level from Warning to Trace
2019-02-08 21:56:47 -05:00
Fernando Sahmkow
e543320129 Implement linear textures (#2089) 2019-02-08 18:28:01 -05:00
bunnei
504aafedd2 Merge pull request #2097 from ReinUsesLisp/fixup-texview
gl_rasterizer_cache: Fixup texture view parameters
2019-02-08 17:30:36 -05:00
ReinUsesLisp
e36e7ae74e gl_rasterizer_cache: Fixup texture view parameters
These parameters were declared as constants and passed to glTextureView
but then they were removed on a rabase. This addresses that mistake.
2019-02-08 18:32:58 -03:00
Tobias
259e52ccb2 nvdisp_disp0: change drawing message log level from Warning to Trace
This is a leftover from the early yuzu days.
We shouldn't log every time when we are drawing by default, so let's change the log level to Trace.
2019-02-08 19:26:49 +01:00
ReinUsesLisp
889c646ac0 shader_ir: Remove F4 prefix to texture operations
This was originally included because texture operations returned a vec4.
These operations now return a single float and the F4 prefix doesn't
mean anything.
2019-02-07 17:36:46 -03:00
ReinUsesLisp
d62b0a9e29 shader_ir: Clean texture management code
Previous code relied on GLSL parameter order (something that's always
ill-formed on an IR design). This approach passes spatial coordiantes
through operation nodes and array and depth compare values in the the
texture metadata. It still contains an "extra" vector containing generic
nodes for bias and component index (for example) which is still a bit
ill-formed but it should be better than the previous approach.
2019-02-07 00:46:13 -03:00
bunnei
f09d1dffd1 Merge pull request #2083 from ReinUsesLisp/shader-ir-cbuf-tracking
shader/track: Add a more permissive global memory tracking
2019-02-06 21:56:14 -05:00
bunnei
35e1118766 gl_rasterizer_cache: Mark surface copy destinations as modified. 2019-02-06 21:54:25 -05:00
bunnei
dd1aab5446 gl_rasterizer: Implement a more accurate fermi 2D copy.
- This is a blit, use the blit registers.
2019-02-06 21:54:21 -05:00
bunnei
ca482997fe Merge pull request #2091 from FearlessTobi/port-4603
Port citra-emu/citra#4603: "gdbstub: only let Execute breakpoints write/restore BKPT opcodes into target memory"
2019-02-06 21:51:46 -05:00
bunnei
e09f1c92fb Merge pull request #2021 from ReinUsesLisp/disk-cache
gl_shader_cache: Disk based shader cache
2019-02-06 21:47:20 -05:00
ReinUsesLisp
dfd14618f7 cmake: Fix title bar issue 2019-02-06 22:23:41 -03:00
Frederic L
d0ac624403 gl_shader_disk_cache: Check LZ4 size limit
Co-Authored-By: ReinUsesLisp <reinuseslisp@airmail.cc>
2019-02-06 22:23:41 -03:00
Frederic L
9f0b247cf6 gl_shader_disk_cache: Consider compressed size zero as an error
Co-Authored-By: ReinUsesLisp <reinuseslisp@airmail.cc>
2019-02-06 22:23:41 -03:00
Frederic L
8ff2ce5207 cmake: Use CMAKE_COMMAND instead of "cmake"
Co-Authored-By: ReinUsesLisp <reinuseslisp@airmail.cc>
2019-02-06 22:23:41 -03:00
ReinUsesLisp
e6a2245304 gl_shader_disk_cache: Use unordered containers 2019-02-06 22:23:41 -03:00
ReinUsesLisp
e147ed4fc0 gl_shader_cache: Fixup GLSL unique identifiers 2019-02-06 22:23:40 -03:00
Michael
4ffb487251 cmake: Fixup application string
Co-Authored-By: ReinUsesLisp <reinuseslisp@airmail.cc>
2019-02-06 22:23:40 -03:00
ReinUsesLisp
bd928e70ed loading_screen: Unchunk progress bar 2019-02-06 22:23:40 -03:00
ReinUsesLisp
eb73247433 gl_shader_cache: Link loading screen with disk shader cache load 2019-02-06 22:23:40 -03:00
ReinUsesLisp
df0f31f44e gl_shader_cache: Set GL_PROGRAM_SEPARABLE to dumped shaders
i965 (and probably all mesa drivers) require GL_PROGRAM_SEPARABLE when using
glProgramBinary. This is probably required by the standard but it's ignored by
permisive proprietary drivers.
2019-02-06 22:23:40 -03:00
ReinUsesLisp
7fefec585c gl_shader_disk_cache: Pass core system as argument and guard against games without title ids 2019-02-06 22:23:40 -03:00
ReinUsesLisp
2bc6a699dc gl_shader_disk_cache: Guard reads and writes against failure 2019-02-06 22:23:40 -03:00
ReinUsesLisp
750abcc23d gl_shader_disk_cache: Address miscellaneous feedback 2019-02-06 22:23:40 -03:00
ReinUsesLisp
8ee3666a3c gl_shader_disk_cache: Pass return values returning instead of by parameters 2019-02-06 22:23:40 -03:00
ReinUsesLisp
ed956569a4 gl_shader_disk_cache: Compress program binaries using LZ4 2019-02-06 22:23:39 -03:00
ReinUsesLisp
f087639e4a gl_shader_disk_cache: Compress GLSL code using LZ4 2019-02-06 22:23:39 -03:00
ReinUsesLisp
cfb20c4c9d gl_shader_disk_cache: Save GLSL and entries into the precompiled file 2019-02-06 22:23:39 -03:00
ReinUsesLisp
e78da8dc1f settings: Hide shader cache behind a setting 2019-02-06 22:20:57 -03:00
ReinUsesLisp
be4641c43f gl_shader_disk_cache: Invalidate shader cache changes with CMake hash 2019-02-06 22:20:57 -03:00
ReinUsesLisp
a3703f5767 gl_shader_cache: Refactor to support disk shader cache 2019-02-06 22:20:57 -03:00
ReinUsesLisp
4039086226 gl_shader_disk_cache: Add transferable cache invalidation 2019-02-06 22:20:57 -03:00
ReinUsesLisp
a1faed9950 gl_shader_disk_cache: Add precompiled load 2019-02-06 22:20:57 -03:00
ReinUsesLisp
57fb15d2a3 gl_shader_disk_cache: Add precompiled save 2019-02-06 22:20:57 -03:00
ReinUsesLisp
3435cd8d5e gl_shader_disk_cache: Add transferable load 2019-02-06 22:20:57 -03:00
ReinUsesLisp
b1efceec89 gl_shader_disk_cache: Add transferable stores 2019-02-06 22:20:57 -03:00
ReinUsesLisp
98be5a4928 gl_shader_disk_cache: Add ShaderDiskCacheOpenGL class and helpers 2019-02-06 22:20:57 -03:00
ReinUsesLisp
145c3ac89e gl_shader_disk_cache: Add file and move BaseBindings declaration 2019-02-06 22:20:57 -03:00
ReinUsesLisp
c2c5260fd7 gl_shader_decompiler: Remove name entries 2019-02-06 22:20:57 -03:00
ReinUsesLisp
8b11368671 gl_shader_util: Add parameter to handle retrievable programs 2019-02-06 22:20:57 -03:00
ReinUsesLisp
0ed5d728ca rasterizer_interface: Add disk cache entry for the rasterizer 2019-02-06 22:20:57 -03:00
ReinUsesLisp
84412591c9 file_util: Add shader directory 2019-02-06 22:20:57 -03:00
ReinUsesLisp
049050856f shader_decode: Implement LDG and basic cbuf tracking 2019-02-06 22:20:57 -03:00
bunnei
10ab714fe0 Merge pull request #2042 from ReinUsesLisp/nouveau-tex
maxwell_3d: Allow texture handles with TIC id zero
2019-02-06 20:19:20 -05:00
bunnei
40ac058557 Merge pull request #2071 from ReinUsesLisp/dsa-texture
gl_rasterizer: Use DSA for textures and move swizzling to texture state
2019-02-06 20:17:59 -05:00
Dimitri ALBORA
8b800369ea gdbstub: only let Execute breakpoints write/restore BKPT opcodes into target memory 2019-02-06 19:07:35 +01:00
bunnei
c357d8f6f7 Merge pull request #2057 from FearlessTobi/port-4586
Port citra-emu/citra#4586: "Use QPixmap/QIcon for background color selection button"
2019-02-06 12:37:57 -05:00
bunnei
b34ae2235d Merge pull request #2086 from FearlessTobi/port-4583
Port citra-emu/citra#4583: "citra_qt: Fix saving screenshot when no file extension is provided"
2019-02-06 12:33:35 -05:00
bunnei
40cd299f01 Merge pull request #2087 from lioncash/const
service/nvflinger, service/vi: Improve error case handling
2019-02-06 12:33:13 -05:00
bunnei
67c1f31251 Merge pull request #2088 from jroweboy/h
QT: Fix the loading screen 'H' switch logo to not glitch out
2019-02-05 21:06:39 -05:00
James Rowe
c82b0afb69 QT: Fix the loading screen 'H' switch logo to not glitch out 2019-02-05 18:24:15 -07:00
Lioncash
ef073ff117 service/nvflinger,service/vi: Handle failure cases with exposed API
Converts many of the Find* functions to return a std::optional<T> as
opposed to returning the raw return values directly. This allows
removing a few assertions and handles error cases like the service
itself does.
2019-02-05 18:03:28 -05:00
bunnei
7aa7d8f4ff Merge pull request #2085 from ReinUsesLisp/cube-minus-one
video_core/texture: Fix BitField size for depth_minus_one
2019-02-05 17:15:26 -05:00
xperia64
f598490b57 Fix crash when no files are selected 2019-02-05 22:40:23 +01:00
xperia64
284536a626 Add file extension to screenshot filename if not provided 2019-02-05 22:31:37 +01:00
Lioncash
7320c667df service/nvflinger: Mark FindVsyncEvent() as a const member function
This member function doesn't actually modify instance state, so it can
be marked as a const member function.
2019-02-05 15:57:29 -05:00
Lioncash
3c02cdcc57 service/nvflinger: Rename GetVsyncEvent() to FindVsyncEvent()
This was missed within #2075. Renames the member function to make it
consistent with the rest of the Find* functions.
2019-02-05 15:55:18 -05:00
bunnei
72c70d6808 Merge pull request #2081 from ReinUsesLisp/lmem-64
shader_ir/memory: Add LD_L 64 bits loads
2019-02-05 09:17:48 -05:00
ReinUsesLisp
b5e685b297 video_core/texture: Fix BitField size for depth_minus_one 2019-02-05 04:32:06 -03:00
bunnei
bb4549a73d Merge pull request #2082 from FernandoS27/txq-stl
Fix TXQ not using the component mask.
2019-02-04 20:22:32 -05:00
Mat M
a568cd805b Update src/video_core/engines/shader_bytecode.h
Co-Authored-By: FernandoS27 <fsahmkow27@gmail.com>
2019-02-03 21:27:26 -04:00
Fernando Sahmkow
0306c50339 Fix TXQ not using the component mask. 2019-02-03 18:17:18 -04:00
ReinUsesLisp
dfa7be5ddf shader_ir/memory: Add ST_L 64 and 128 bits stores 2019-02-03 19:08:10 -03:00
ReinUsesLisp
0d1d755086 shader/track: Search inside of conditional nodes
Some games search conditionally use global memory instructions. This
allows the heuristic to search inside conditional nodes for the source
constant buffer.
2019-02-03 17:21:20 -03:00
ReinUsesLisp
42b75e8be8 shader_ir: Rename BasicBlock to NodeBlock
It's not always used as a basic block. Rename it for consistency.
2019-02-03 17:21:20 -03:00
ReinUsesLisp
6a6fabea58 shader_ir: Pass decoded nodes as a whole instead of per basic blocks
Some games call LDG at the top of a basic block, making the tracking
heuristic to fail. This commit lets the heuristic the decoded nodes as a
whole instead of per basic blocks.

This may lead to some false positives but allows it the heuristic to
track cases it previously couldn't.
2019-02-03 17:21:20 -03:00
ReinUsesLisp
2bdbb90af7 video_core: Assert on invalid GPU to CPU address queries 2019-02-03 04:58:40 -03:00
ReinUsesLisp
04e68e9738 maxwell_3d: Allow sampler handles with TSC id zero 2019-02-03 04:58:40 -03:00
ReinUsesLisp
390721a561 maxwell_3d: Allow texture handles with TIC id zero
Also remove "enabled" field from Tegra::Texture::FullTextureInfo because
it would become unused.
2019-02-03 04:58:24 -03:00
ReinUsesLisp
e01a9de35f memory_manager: Check for reserved page status 2019-02-03 04:58:24 -03:00
ReinUsesLisp
f61c1ed246 shader_ir/memory: Add LD_L 128 bits loads 2019-02-03 00:35:34 -03:00
ReinUsesLisp
9feb68085d shader_bytecode: Rename BytesN enums to BitsN 2019-02-03 00:25:40 -03:00
ReinUsesLisp
0be835132c shader_ir/memory: Add LD_L 64 bits loads 2019-02-03 00:25:40 -03:00
bunnei
eceab45dac Merge pull request #2074 from ReinUsesLisp/shader-ir-unify-offset
shader_ir: Unify constant buffer offset values
2019-02-01 13:24:04 -05:00
bunnei
4076d8fe3e Merge pull request #2073 from lioncash/opus
hwopus: Implement DecodeInterleaved (the newest variant)
2019-02-01 13:02:16 -05:00
bunnei
2d226ff8ac Merge pull request #2067 from ReinUsesLisp/workaround-fb
gl_rasterizer: Workaround invalid zeta clears
2019-02-01 12:50:09 -05:00
bunnei
11e7c1244c Merge pull request #2078 from lioncash/timer
kernel: Remove the Timer class
2019-02-01 12:49:16 -05:00
bunnei
3a6eef27a2 Merge pull request #2079 from ReinUsesLisp/remove-fill
video_core: Remove unused Fill related code
2019-02-01 12:48:38 -05:00
ReinUsesLisp
26f8a700a7 rasterizer_interface: Remove unused AccelerateFill operation 2019-02-01 03:02:22 -03:00
ReinUsesLisp
13222f94c0 video_core: Remove unused Fill surface type 2019-02-01 02:57:47 -03:00
Lioncash
414cc1eb1f kernel: Remove the Timer class
A holdover from citra, the Horizon kernel on the switch has no
prominent kernel object that functions as a timer. At least not
to the degree of sophistication that this class provided.

As such, this can be removed entirely. This class also wasn't used at
all in any meaningful way within the core, so this was just code sitting
around doing nothing. This also allows removing a few things from the
main KernelCore class that allows it to use slightly less resources
overall (though very minor and not anything really noticeable).
2019-01-31 23:05:15 -05:00
bunnei
b0b027d2d0 Merge pull request #2072 from lioncash/service
service: Update function tables
2019-01-31 15:19:44 -05:00
bunnei
db21ac2627 Merge pull request #2077 from lioncash/virt
kernel/wait_object: Devirtualize functions related to manipulating the thread list directly
2019-01-31 15:19:02 -05:00
bunnei
d6f5f5cafa Merge pull request #2075 from lioncash/find
service/nvflinger: Minor renaming changes
2019-01-31 11:08:36 -05:00
ReinUsesLisp
3e80b08944 gl_rasterizer_cache: Fixup test clause 2019-01-30 19:10:35 -03:00
Mat M
911587fb8d gl_rasterizer_cache: Guard clause swizzle testing
Co-Authored-By: ReinUsesLisp <reinuseslisp@airmail.cc>
2019-01-30 19:10:35 -03:00
ReinUsesLisp
220df45b7d gl_state: Remove texture target tracking 2019-01-30 19:10:35 -03:00
ReinUsesLisp
704744bb72 gl_rasterizer_cache: Move swizzling to textures instead of state 2019-01-30 19:10:35 -03:00
ReinUsesLisp
3bbaa98c78 gl_state: Use DSA and multi bind to update texture bindings 2019-01-30 19:10:11 -03:00
ReinUsesLisp
4b676e7786 gl_rasterizer: Use DSA for textures 2019-01-30 19:10:11 -03:00
Hexagon12
e597665569 Merge pull request #1818 from ccawley2011/patch-1
Add missing environment variables to travis-ci.env
2019-01-30 19:53:34 +02:00
Lioncash
a3cdd773c3 kernel/wait_object: Devirtualize functions related to manipulating the thread list directly
No inheritors of the WaitObject class actually make use of their own
implementations of these functions, so they can be made non-virtual.

It's also kind of sketchy to allow overriding how the threads get added
to the list anyways, given the kernel itself on the actual hardware
doesn't seem to customize based off this.
2019-01-30 12:50:37 -05:00
Lioncash
4596ef5274 kernel/timer: Remove unnecessary WakeupAllWaitingThreads() override
This implementation just calls the base class variant of the function,
so this isn't necessary.
2019-01-30 12:45:00 -05:00
Lioncash
1a302d4d47 kernel/readable_event: Remove unnecessary WakeupAllWaitingThreads() override
This just calls the base variant of the function, so it can be removed.
2019-01-30 12:45:00 -05:00
Hexagon12
35480167b1 Merge pull request #2076 from lioncash/enc
video_core/dma_pusher: Silence C4828 warnings
2019-01-30 19:42:15 +02:00
Lioncash
0b594f3344 video_core/dma_pusher: Silence C4828 warnings
This was previously causing:

warning C4828: The file contains a character starting at offset 0xa33
that is illegal in the current source character set (codepage 65001).

warnings on Windows when compiling yuzu.
2019-01-30 12:36:31 -05:00
bunnei
92b18345a8 Merge pull request #1485 from FernandoS27/render-info
Add more info into textures' object labels
2019-01-30 12:35:56 -05:00
Lioncash
a897feb21e hwopus: Implement DecodeInterleaved
This functions almost identically to DecodeInterleavedWithPerfOld,
however this function also has the ability to reset the decoder context.

This is documented as a potentially desirable thing in the libopus
manual in some circumstances as it says for the OPUS_RESET_STATE ctl:

"This should be called when switching streams in order to prevent the
back to back decoding from giving different result from one at a time
decoding."
2019-01-30 11:35:41 -05:00
Lioncash
ba14fb42e4 service/nvflinger: Make FindBufferQueueId() a const member function
This member function doesn't actually modify instance state, so it can
be const-qualified.
2019-01-30 11:14:08 -05:00
Lioncash
1d11def9c4 service/nvflinger: Rename Get prefix on function to Find
This more accurately describes what the function is actually attempting
to do (it's not a simple trivial getter).
2019-01-30 11:11:32 -05:00
ReinUsesLisp
477d616f7d shader_ir: Unify constant buffer offset values
Constant buffer values on the shader IR were using different offsets if
the access direct or indirect. cbuf34 has a non-multiplied offset while
cbuf36 does. On shader decoding this commit multiplies it by four on
cbuf34 queries.
2019-01-30 02:45:50 -03:00
Lioncash
07b86dc28c hwopus: Deduplicate the decoding code within DecodeInterleavedOld and DecodeInterleavedWithPerfOld
Keeps the logic in one spot for use by both functions.
2019-01-29 22:53:35 -05:00
Lioncash
44f39bfb68 hwopus: Replace std::optional<std::reference_wrapper<u64>> with u64*
This doesn't really offer anything over the use of a direct pointer, so
we can just use that instead.
2019-01-29 22:53:35 -05:00
Lioncash
eb1a3c1f4a hwopus: Mark local variables as const where applicable
Makes non-mutable state more explicit.
2019-01-29 22:53:35 -05:00
Lioncash
06887c80a5 hwopus: Fill in the rest of the unknown service function names
Filled in via information provided by SwitchBrew.
2019-01-29 22:53:34 -05:00
Lioncash
5078106068 service/ns: Update function tables
Updates function tables based off information provided by SwitchBrew
2019-01-29 22:50:26 -05:00
Lioncash
1710847d08 service/ncm: Update function tables
Updates function tables based off information provided by SwitchBrew
2019-01-29 22:50:26 -05:00
Lioncash
0db8918947 service/audio: Update function tables
Updates function tables based off information provided by SwitchBrew.
2019-01-29 22:50:26 -05:00
Lioncash
c3affdd162 service/am/applet_ae: Update function tables
Updates function tables based off information provided by SwitchBrew.
2019-01-29 22:50:26 -05:00
Lioncash
09727a6a97 service/fsp-srv: Update function tables
Updates function tables based off information provided by SwitchBrew.
2019-01-29 22:50:26 -05:00
Lioncash
c6c1c1b45f service/btm: Update function tables
Updates function tables based off information provided by SwitchBrew
2019-01-29 22:50:26 -05:00
Lioncash
0c59e6265f service/btdrv: Update function tables
Updates function tables based off information provided by SwitchBrew.
2019-01-29 22:50:18 -05:00
bunnei
3c3d9afd61 Merge pull request #2070 from ReinUsesLisp/cubearray-view
gl_shader_cache: Fix texture view for cubemaps as cubemap arrays
2019-01-29 22:27:08 -05:00
bunnei
69884d8a8f Merge pull request #2069 from lioncash/vi
service/nvflinger: Add the null display type
2019-01-29 22:25:26 -05:00
bunnei
4c818b60e3 Merge pull request #1987 from ReinUsesLisp/explicit-shader-ldg
gl_shader_cache: Use explicit bindings
2019-01-29 22:15:55 -05:00
ReinUsesLisp
52c326c301 gl_shader_cache: Use explicit bindings 2019-01-30 00:11:02 -03:00
bunnei
52bb524526 Merge pull request #1960 from ReinUsesLisp/shader-ir-ldg
video_core: Implement LDG through heuristics based on IR
2019-01-29 22:02:01 -05:00
ReinUsesLisp
9f803299de gl_rasterizer: Implement global memory management 2019-01-30 00:00:15 -03:00
ReinUsesLisp
3b84e04af1 shader_decode: Implement LDG and basic cbuf tracking 2019-01-30 00:00:15 -03:00
Kevin
ba38d91fe2 video_core/GPU Implemented the GPU PFIFO puller semaphore operations. (#1908)
* Implemented the puller semaphore operations.

* Nit: Fix 2 style issues

* Nit: Add Break to default case.

* Fix style.

* Update for comments. Added ReferenceCount method

* Forgot to remove GpuSmaphoreAddress union.

* Fix the clang-format issues.

* More clang formatting.

* two more white spaces for the Clang formatting.

* Move puller members into the regs union

* Updated to use Memory::WriteBlock instead of Memory::Write*

* Fix clang style issues

* White space clang error

* Removing unused funcitons and other pr comment

* Removing unused funcitons and other pr comment

* More union magic for setting regs value.

* union magic refcnt as well

*  Remove local var

* Set up the regs and regs_assert_positions up properly

* Fix clang error
2019-01-29 21:49:18 -05:00
ReinUsesLisp
f58a6152fc gl_shader_cache: Fix texture view for cubemaps as cubemap arrays
Cubemaps are considered layered and to create a texture view the texture
mustn't be a layered texture, resulting in cubemaps being bound as
cubemap arrays. To fix this issue this commit introduces an extra
surface parameter called "is_array" and uses this to query for texture
view creation.

Now that texture views for cubemaps are actually being created, this
also fixes the number of layers created for the texture view (since they
have to be 6 to create a texture view of cubemaps).
2019-01-29 23:49:02 -03:00
ReinUsesLisp
07692230ca gl_rasterizer: Workaround invalid zeta clears
Some games (like Xenoblade Chronicles 2) clear both depth and stencil
buffers while there's a depth-only texture attached (e.g. D16 Unorm).
This commit reads the zeta format of the bound surface on
ConfigureFramebuffers and returns if depth and/or stencil attachments
were set. This is ignored on DrawArrays but on Clear it's used to just
clear those attachments, bypassing an OpenGL error.
2019-01-29 23:47:33 -03:00
Lioncash
49a3571e76 service/psc: Update function tables
Updates the function tables based off information on SwitchBrew. Gets
rid of a swath of unknown names.
2019-01-29 21:16:24 -05:00
Lioncash
7e92497402 nvflinger: Add the Null display
In addition to the default, external, EDID, and internal displays,
there's also a null display provided as well, which as the name
suggests, does nothing but discard all commands given to it. This is
provided for completeness.
2019-01-29 21:13:33 -05:00
Lioncash
679e63550a nvflinger: Change log message in OpenDisplay to be a debug log instead of a warning
Opening a display isn't really a thing to warn about. It's an expected
thing, so this can be a debug log. This also alters the string to
indicate the display name better.

Opening "Default" display reads a little nicer compared to Opening
display Default.
2019-01-29 21:13:33 -05:00
Lioncash
3d81a8efd5 nvflinger: Remove unnecessary header inclusions 2019-01-29 21:13:33 -05:00
Lioncash
d9f9bb7552 nvflinger: Mark locals const where applicable
Makes non-mutable state more explicit.
2019-01-29 21:13:33 -05:00
Lioncash
f45c25aaba nvflinger: Use a std::array for the available displays instead of std::vector
The built-in set of displays is fixed, so we can utilize an array
instead of a vector here.
2019-01-29 21:13:33 -05:00
Lioncash
2561a79c39 hle/ipc_helpers: Fix clang-format warnings 2019-01-29 21:11:04 -05:00
Lioncash
ac603cf130 hle/ipc_helpers: Allow pushing signed values
This is kind of a large hole in the API, given we allow popping signed
values. This fixes that.
2019-01-29 13:09:32 -05:00
bunnei
8dbb8edcd3 Merge pull request #2063 from lioncash/pessimizing
video_core/shader: Minor changes
2019-01-28 19:33:26 -05:00
bunnei
c608d3a979 Merge pull request #2065 from lioncash/pm
service/pm: Implement SetMaintenanceBoot
2019-01-28 19:32:32 -05:00
Lioncash
932922f67f service/pm: Implement SetMaintenanceBoot()
This quite literally functions as a basic setter. No other error
checking or anything (since there's nothing to really check against).

With this, it completes the pm:bm interface in terms of functionality.
2019-01-28 11:48:11 -05:00
Lioncash
cb2ce9924a service/pm: Tidy up functionality related to SystemBootMode
Just minor tidying of interfaces.
2019-01-28 11:44:37 -05:00
bunnei
72c48e01c9 Merge pull request #2064 from lioncash/vi-stub
service/vi: Remove stubbed notifier from SetLayerVisibility
2019-01-28 11:05:07 -05:00
Lioncash
5e636d1f6e service/vi: Remove stubbed notifier from SetLayerVisibility
This appears to be a vestigial API function that's only kept around for
compatibility's sake, given the function only returns a success error
code and exits.

Since that's the case, we can remove the stubbed notification from the
log, since doing nothing is technically the correct behavior in this
case.
2019-01-28 08:22:28 -05:00
Lioncash
b2b98b2f44 shader/shader_ir: Amend three comment typos
Given we're in the area, these are three trivial typos that can be
corrected.
2019-01-28 07:52:04 -05:00
Lioncash
62e08c30b7 shader/shader_ir: Amend constructor initializer ordering for AbufNode
Orders the class members in the same order that they would actually be
initialized in. Gets rid of two compiler warnings.
2019-01-28 07:50:34 -05:00
Lioncash
3e1a9a45a6 shader/decode: Avoid a pessimizing std::move within DecodeRange()
std::moveing a local variable in a return statement has the potential to
prevent copy elision from occurring, so this can just be converted into
a regular return.
2019-01-28 07:43:23 -05:00
bunnei
a9268286a4 Merge pull request #2060 from lioncash/exception
kernel/svc: Log out uncaught C++ exceptions from svcBreak
2019-01-27 12:55:07 -05:00
bunnei
65f3908064 Merge pull request #2058 from ReinUsesLisp/trunc-warning
video_core: Silent implicit conversion warning
2019-01-27 12:49:59 -05:00
bunnei
6957bac03c Merge pull request #2059 from FearlessTobi/port-4601
Port citra-emu/citra#4601: "dsp_interface: fix sound being played while volume is 0"
2019-01-26 21:21:04 -05:00
Lioncash
7842536ddb kernel/svc: Log out uncaught C++ exceptions from svcBreak
Looking into the implementation of the C++ standard facilities that seem
to be within all modules, it appears that they use 7 as a break reason
to indicate an uncaught C++ exception.

This was primarily found via the third last function called within
Horizon's equivalent of libcxxabi's demangling_terminate_handler(),
which passes the value 0x80000007 to svcBreak.
2019-01-26 21:19:13 -05:00
fearlessTobi
7185d90a53 dsp_interface: fix sound being played while volume is 0
According to documentation, if the argument of std::exp is zero, one is returned.
However we want the return value to be also zero in this case so no audio is played.
2019-01-26 22:42:09 +01:00
xperia64
32eb080e02 Use QPixmap/QIcon for background color selection button 2019-01-26 15:08:54 +01:00
ReinUsesLisp
fc6d46c374 video_core: Silent implicit conversion warning 2019-01-26 02:27:14 -03:00
bunnei
1f4ca1e841 Merge pull request #1927 from ReinUsesLisp/shader-ir
video_core: Replace gl_shader_decompiler with an IR based decompiler
2019-01-25 23:42:14 -05:00
bunnei
f574d324e7 Merge pull request #2054 from bunnei/scope-context-refactor
frontend: Refactor ScopeAcquireWindowContext out of renderer_opengl.
2019-01-23 21:20:08 -05:00
bunnei
9be3fedcaa Merge pull request #2049 from FearlessTobi/port-3928
Port citra-emu/citra#3928: "citra_qt: Log settings on launch"
2019-01-23 20:46:37 -05:00
bunnei
045b0b70b6 frontend: Refactor ScopeAcquireWindowContext out of renderer_opengl. 2019-01-23 19:19:23 -05:00
zhupengfei
a94a828b6c citra_qt: Log settings on launch 2019-01-22 23:35:38 +01:00
bunnei
d5a4707f65 Merge pull request #2047 from FearlessTobi/patch-3
ISSUE_TEMPLATE: changes to make it more expressive and prevent low-quality issues
2019-01-22 16:00:17 -05:00
Tobias
a6f473fd01 ISSUE_TEMPLATE: changes to make it more expressive and prevent low-quality issues 2019-01-22 21:52:59 +01:00
bunnei
0fa1ebc349 Merge pull request #2043 from ReinUsesLisp/rt-separate
maxwell_3d: Set rt_separate_frag_data to 1 by default
2019-01-22 09:23:35 -05:00
ReinUsesLisp
9a82dec74a maxwell_3d: Set rt_separate_frag_data to 1 by default
Commercial games assume that this value is 1 but they never set it. On
the other hand nouveau manually sets this register. On
ConfigureFramebuffers we were asserting for what we are actually
implementing (according to envytools).
2019-01-22 04:14:29 -03:00
bunnei
839c4a8a1c Merge pull request #2035 from lioncash/fwd-decl
yuzu/configuration: Remove unnecessary inclusions where applicable
2019-01-21 17:31:07 -05:00
bunnei
125599c2d5 Merge pull request #2038 from jroweboy/loading-progress-bar
Loading progress bar upgrades
2019-01-21 14:12:47 -05:00
James Rowe
3049ea45d3 Change const char* to const char[] 2019-01-21 10:28:32 -07:00
James Rowe
372245e0b5 Fix mingw compile error and warnings 2019-01-21 09:39:45 -07:00
James Rowe
3ca0af8bb3 Add fade out effect to the loading screen 2019-01-21 09:20:16 -07:00
James Rowe
3740adb6f5 Set Minimum Size to the same as renderwindow 2019-01-21 08:51:37 -07:00
James Rowe
aa427bb2a7 Remove blue box around loading screen 2019-01-21 08:50:23 -07:00
James Rowe
636cc2a496 Change the background color of Stage Complete to yuzu blue 2019-01-20 19:14:14 -07:00
James Rowe
ea73ffe202 Rename step 1 and step 2 to be a little more descriptive 2019-01-20 18:40:25 -07:00
James Rowe
56541b1ae5 Prevent estimated time from flashing after slow shader compilation starts 2019-01-20 18:31:35 -07:00
James Rowe
4bce57b149 Move progress bar style into constexpr strings 2019-01-20 18:20:21 -07:00
James Rowe
63783db1b3 Hide progress bar on Prepare step 2019-01-20 15:09:14 -07:00
James Rowe
e8bd6b1fcc QT: Upgrade the Loading Bar to look much better 2019-01-20 14:47:35 -07:00
bunnei
1c733bf175 Merge pull request #2034 from jroweboy/loading-widget
QT Frontend: Add a Loading screen with progressbar
2019-01-20 15:45:07 -05:00
bunnei
197d0d9d24 Merge pull request #2008 from ReinUsesLisp/dirty-framebuffers
gl_rasterizer_cache: Use dirty flags for framebuffers
2019-01-20 14:06:26 -05:00
bunnei
cbf8bea9d5 Merge pull request #2002 from ReinUsesLisp/dsa-vao-buffer
gl_rasterizer: Use DSA for VAOs and buffers
2019-01-20 14:06:01 -05:00
bunnei
eff61c5c42 Merge pull request #2032 from lioncash/web
yuzu/configuration/configure_web: Amend verification string
2019-01-20 13:26:47 -05:00
bunnei
f9e69faf4a Merge pull request #2025 from DarkLordZach/loader-banner-logo
loader: Add getters for application banner and logo
2019-01-20 13:26:27 -05:00
James Rowe
69da267540 Add a workaround if QMovie isn't available 2019-01-19 23:34:03 -07:00
James Rowe
08fcf41b0a QT Frontend: Add a Loading screen with progressbar
With shader caches on the horizon, one requirement is to provide visible
feedback for the progress. The shader cache reportedly takes several
minutes to load for large caches that were invalidated, and as such we
should provide a loading screen with progress.

Adds a loading screen widget that will be shown until the first frame of
the game is swapped. This was chosen in case shader caches are not being
used, several games still take more than a few seconds to launch and
could benefit from a loading screen.
2019-01-19 23:34:03 -07:00
bunnei
83f8d1aa2e Merge pull request #2031 from lioncash/priv
yuzu/web_browser: Minor cleanup
2019-01-19 12:57:09 -05:00
bunnei
966405d64b Merge pull request #2033 from ReinUsesLisp/fixup-clip-warning
gl_rasterizer: Silent unsafe mix warning
2019-01-19 12:56:40 -05:00
bunnei
d0e4e43e3c Merge pull request #2036 from lioncash/unused-class
file_sys/directory: Remove unused DirectoryBackend class
2019-01-19 12:56:16 -05:00
Lioncash
96644385ca file_sys/directory: Remove unused DirectoryBackend class
This isn't used at all, so we can just get rid of it.
2019-01-18 14:33:50 -05:00
ReinUsesLisp
a1b1ea47ed gl_rasterizer: Silent unsafe mix warning 2019-01-18 03:25:28 -03:00
Lioncash
faf69a22d4 yuzu/configuration/configure_input_player: Forward declare types where applicable
Allows removing the inclusion of the main input common header from the
UI config header.
2019-01-17 12:08:15 -05:00
Lioncash
609e98bc63 yuzu/configuration/configure_touchscreen_advanced: Remove unnecessary header inclusions 2019-01-17 12:02:01 -05:00
Lioncash
a0f615f232 yuzu/configuration/configure_per_general: Remove unused header inclusions 2019-01-17 11:58:43 -05:00
Lioncash
ac754a57d2 yuzu/configuration/configure_debug: Remove unused header inclusions 2019-01-17 11:51:47 -05:00
Lioncash
3629fcf3e6 yuzu/configuration/configure_system: Remove unused header inclusions 2019-01-17 11:50:57 -05:00
Lioncash
549164d425 yuzu/configuration/configure_web: Remove an unused lambda capture
'this' isn't actually used within the lambda, since what we need
from the class is already assigned within the capture section of
the lambda.
2019-01-17 11:39:49 -05:00
Lioncash
b8b87ec01f yuzu/configuration/configure_web: Use an ellipsis with 'Verifying' text
It's a common UI pattern to use an ellipsis to indicate an ongoing
action, rather than just specifying the word by itself.
2019-01-17 11:35:59 -05:00
Lioncash
5961928543 core/frontend/applets/web_browser: Include missing headers
Gets rid of a few indirect inclusions.
2019-01-17 11:25:37 -05:00
Lioncash
a661025637 core/frontend/applets/web_browser: Make OpenPage() non-const
This is a function that definitely doesn't always have a non-modifying
behavior across all implementations, so this should be made non-const.

This gets rid of the need to mark data members as mutable to work around
the fact mutating data members needs to occur.
2019-01-17 11:19:52 -05:00
Lioncash
66978a772d yuzu/web_browser: std::move std::function instances in OpenPage()
Avoids the need to potentially reallocate the contained callbacks.
2019-01-17 11:10:35 -05:00
Lioncash
e4fa77ef6a yuzu/web_browser: Make slot functions private
These currently aren't used by anything other than the QtWebBrowser
class itself, and can be made private.
2019-01-17 11:08:05 -05:00
ReinUsesLisp
a63d7c49fc shader_ir: Fixup clang build 2019-01-15 21:06:05 -03:00
Zach Hilman
b273b19576 loader: Propagate NCA logo section to ReadBanner and ReadLogo 2019-01-15 16:01:04 -05:00
Zach Hilman
318bf7c8e3 content_archive: Add getter for logo section of NCA 2019-01-15 16:00:29 -05:00
ReinUsesLisp
1e40a4b343 gl_shader_decompiler: replace std::get<> with std::get_if<> for macOS compatibility 2019-01-15 17:54:53 -03:00
ReinUsesLisp
51de4e00a6 gl_shader_decompiler: Inline textureGather component 2019-01-15 17:54:53 -03:00
ReinUsesLisp
1c9c4eefeb shader_decode: Fixup XMAD 2019-01-15 17:54:53 -03:00
ReinUsesLisp
170c8212bb shader_ir: Pass to decoder functions basic block's code 2019-01-15 17:54:53 -03:00
ReinUsesLisp
2d6c064e66 shader_decode: Improve zero flag implementation 2019-01-15 17:54:53 -03:00
ReinUsesLisp
d911740e5d shader_ir: Remove composite primitives and use temporals instead 2019-01-15 17:54:53 -03:00
ReinUsesLisp
bb12f99b20 gl_shader_decompiler: Fixup AssignCompositeHalf 2019-01-15 17:54:53 -03:00
ReinUsesLisp
50195b1704 shader_decode: Use proper primitive names 2019-01-15 17:54:53 -03:00
ReinUsesLisp
2faad9bf23 shader_decode: Use BitfieldExtract instead of shift + and 2019-01-15 17:54:53 -03:00
ReinUsesLisp
52223313b1 shader_ir: Remove Ipa primitive 2019-01-15 17:54:53 -03:00
ReinUsesLisp
d6b173d5fe gl_shader_decompiler: Use rasterizer's UBO size limit 2019-01-15 17:54:53 -03:00
ReinUsesLisp
df74ff3c8b gl_shader_gen: Fixup code formatting 2019-01-15 17:54:53 -03:00
ReinUsesLisp
af5d7e2c49 video_core: Rename glsl_decompiler to gl_shader_decompiler 2019-01-15 17:54:53 -03:00
ReinUsesLisp
d9118d324a shader_ir: Remove RZ and use Register::ZeroIndex instead 2019-01-15 17:54:53 -03:00
ReinUsesLisp
5af82a8ed4 shader_decode: Implement TEXS.F16 2019-01-15 17:54:53 -03:00
ReinUsesLisp
c68c13e1aa shader_decode: Fixup R2P 2019-01-15 17:54:53 -03:00
ReinUsesLisp
8b5588e776 glsl_decompiler: Fixup TLDS 2019-01-15 17:54:53 -03:00
ReinUsesLisp
dbed6c6485 glsl_decompiler: Fixup geometry shaders 2019-01-15 17:54:53 -03:00
ReinUsesLisp
ea78c78253 shader_decode: Fixup WriteLogicOperation zero comparison 2019-01-15 17:54:53 -03:00
ReinUsesLisp
ab7f52b279 glsl_decompiler: Fixup permissive member function declarations 2019-01-15 17:54:53 -03:00
ReinUsesLisp
55a10d02e5 shader_decode: Fixup PSET 2019-01-15 17:54:53 -03:00
ReinUsesLisp
a2e22b4359 shader_decode: Fixup clang-format 2019-01-15 17:54:53 -03:00
ReinUsesLisp
e1fea1e0c5 video_core: Implement IR based geometry shaders 2019-01-15 17:54:53 -03:00
ReinUsesLisp
a1b845b651 shader_decode: Implement VMAD and VSETP 2019-01-15 17:54:53 -03:00
ReinUsesLisp
b11e0b94c7 shader_decode: Implement HSET2 2019-01-15 17:54:53 -03:00
ReinUsesLisp
2df55985b6 shader_decode: Rework HSETP2 2019-01-15 17:54:53 -03:00
ReinUsesLisp
8332482c24 shader_decode: Implement R2P 2019-01-15 17:54:53 -03:00
ReinUsesLisp
3f1136ac6f shader_decode: Implement CSETP 2019-01-15 17:54:52 -03:00
ReinUsesLisp
7e13e8bfcb shader_decode: Implement PSET 2019-01-15 17:54:52 -03:00
ReinUsesLisp
dd91650aaf shader_decode: Implement HFMA2 2019-01-15 17:54:52 -03:00
ReinUsesLisp
d6f76307fe glsl_decompiler: Remove HNegate inlining 2019-01-15 17:54:52 -03:00
ReinUsesLisp
027f443e69 shader_decode: Implement POPC 2019-01-15 17:54:52 -03:00
ReinUsesLisp
55e6786254 shader_decode: Implement TLDS (untested) 2019-01-15 17:54:52 -03:00
ReinUsesLisp
ec98e4d842 shader_decode: Update TLD4 reflecting #1862 changes 2019-01-15 17:54:52 -03:00
ReinUsesLisp
03e088a4f4 shader_ir: Fixup TEX and TEXS and partially fix TLD4 decompiling 2019-01-15 17:54:52 -03:00
ReinUsesLisp
2d9136cec6 shader_decode: Fixup FSET 2019-01-15 17:54:52 -03:00
ReinUsesLisp
af5c6e4ccb shader_decode: Implement IADD32I 2019-01-15 17:54:52 -03:00
ReinUsesLisp
4316eaf75c shader_decode: Fixup clang-format 2019-01-15 17:54:52 -03:00
ReinUsesLisp
fc46ecddb3 video_core: Return safe values after an assert hits 2019-01-15 17:54:52 -03:00
ReinUsesLisp
148a6418ed shader_decode: Implement FFMA 2019-01-15 17:54:52 -03:00
ReinUsesLisp
21aff36459 video_core: Address feedback 2019-01-15 17:54:52 -03:00
ReinUsesLisp
59b34b1d76 shader_ir: Fixup file inclusions and clang-format 2019-01-15 17:54:52 -03:00
Mat M
57a900cc45 shader_ir: Move comment node string
Co-Authored-By: ReinUsesLisp <reinuseslisp@airmail.cc>
2019-01-15 17:54:52 -03:00
ReinUsesLisp
d4fae3a699 shader_ir: Address feedback to avoid UB in bit casting 2019-01-15 17:54:52 -03:00
ReinUsesLisp
946c86f0bb shader_decode: Fixup clang-format 2019-01-15 17:54:52 -03:00
ReinUsesLisp
c9cf899d18 shader_decode: Implement LEA 2019-01-15 17:54:52 -03:00
ReinUsesLisp
4fd06efeb9 shader_decode: Implement IADD3 2019-01-15 17:54:52 -03:00
ReinUsesLisp
a40fd07516 shader_decode: Implement LOP3 2019-01-15 17:54:52 -03:00
ReinUsesLisp
b184ca9089 shader_decode: Implement ST_L 2019-01-15 17:54:52 -03:00
ReinUsesLisp
8d42feb09b shader_decode: Implement LD_L 2019-01-15 17:54:52 -03:00
ReinUsesLisp
21f9e9da09 shader_decode: Implement HSETP2 2019-01-15 17:54:52 -03:00
ReinUsesLisp
68c99d2597 shader_decode: Implement HADD2 and HMUL2 2019-01-15 17:54:52 -03:00
ReinUsesLisp
cf4a08d950 shader_decode: Implement HADD2_IMM and HMUL2_IMM 2019-01-15 17:54:52 -03:00
ReinUsesLisp
376a837511 shader_decode: Implement MOV_SYS 2019-01-15 17:54:52 -03:00
ReinUsesLisp
518a2bd206 shader_decode: Implement IMNMX 2019-01-15 17:54:52 -03:00
ReinUsesLisp
07944a2345 shader_decode: Implement F2F_C 2019-01-15 17:54:52 -03:00
ReinUsesLisp
e8235c0215 shader_decode: Implement I2I 2019-01-15 17:54:52 -03:00
ReinUsesLisp
6ca31f544a shader_decode: Implement BRA internal flag 2019-01-15 17:54:52 -03:00
ReinUsesLisp
210620ff31 shader_decode: Implement ISCADD 2019-01-15 17:54:52 -03:00
ReinUsesLisp
b0e7920838 shader_decode: Implement XMAD 2019-01-15 17:54:51 -03:00
ReinUsesLisp
becfdb8638 shader_decode: Implement PBK and BRK 2019-01-15 17:54:51 -03:00
ReinUsesLisp
8f37531f8e shader_decode: Implement LOP 2019-01-15 17:54:51 -03:00
ReinUsesLisp
8486e7f8c8 shader_decode: Implement SEL 2019-01-15 17:54:51 -03:00
ReinUsesLisp
ccb71bece9 shader_decode: Implement IADD 2019-01-15 17:54:51 -03:00
ReinUsesLisp
faadae5814 shader_decode: Implement ISETP 2019-01-15 17:54:51 -03:00
ReinUsesLisp
80183de884 shader_decode: Implement BFI 2019-01-15 17:54:51 -03:00
ReinUsesLisp
078ba28e13 shader_decode: Implement ISET 2019-01-15 17:54:51 -03:00
ReinUsesLisp
acdbbb8885 shader_decode: Implement LD_C 2019-01-15 17:54:51 -03:00
ReinUsesLisp
d79c462af0 shader_decode: Implement SHL 2019-01-15 17:54:51 -03:00
ReinUsesLisp
a2819c204f shader_decode: Implement SHR 2019-01-15 17:54:51 -03:00
ReinUsesLisp
39f1c6246a shader_decode: Implement LOP32I 2019-01-15 17:54:51 -03:00
ReinUsesLisp
501284a81a shader_decode: Implement BFE 2019-01-15 17:54:51 -03:00
ReinUsesLisp
e444a6553f shader_decode: Implement FSET 2019-01-15 17:54:51 -03:00
ReinUsesLisp
3052eae25e shader_decode: Implement F2I 2019-01-15 17:54:51 -03:00
ReinUsesLisp
8abe5ba2c8 shader_decode: Implement I2F 2019-01-15 17:54:51 -03:00
ReinUsesLisp
c849b5b320 shader_decode: Implement F2F 2019-01-15 17:54:50 -03:00
ReinUsesLisp
9118deb990 shader_decode: Stub DEPBAR 2019-01-15 17:54:50 -03:00
ReinUsesLisp
97f33f00cf shader_decode: Implement SSY and SYNC 2019-01-15 17:54:50 -03:00
ReinUsesLisp
abdbafbc20 shader_decode: Implement PSETP 2019-01-15 17:54:50 -03:00
ReinUsesLisp
802c23b8a8 shader_decode: Implement TMML 2019-01-15 17:54:50 -03:00
ReinUsesLisp
2b90637f4b shader_decode: Implement TEX and TXQ 2019-01-15 17:54:50 -03:00
ReinUsesLisp
878672f371 shader_decode: Implement TEXS (F32) 2019-01-15 17:54:50 -03:00
ReinUsesLisp
c703f0aee4 shader_decode: Implement FSETP 2019-01-15 17:54:50 -03:00
ReinUsesLisp
8215ae942c shader_decode: Partially implement BRA 2019-01-15 17:54:50 -03:00
ReinUsesLisp
4f95dc950e shader_decode: Implement IPA 2019-01-15 17:54:50 -03:00
ReinUsesLisp
cacb934f21 shader_decode: Implement EXIT 2019-01-15 17:54:50 -03:00
ReinUsesLisp
0c049e0a21 shader_decode: Implement ST_A 2019-01-15 17:54:50 -03:00
ReinUsesLisp
e3f1233ce1 shader_decode: Implement LD_A 2019-01-15 17:54:50 -03:00
ReinUsesLisp
ea358bd4bf shader_decode: Implement FADD32I 2019-01-15 17:54:50 -03:00
ReinUsesLisp
c9b2a1b051 shader_decode: Implement FMUL32_IMM 2019-01-15 17:54:50 -03:00
ReinUsesLisp
2edee801ce shader_decode: Implement MOV32_IMM 2019-01-15 17:54:50 -03:00
ReinUsesLisp
06cb910c6d shader_decode: Stub RRO_C, RRO_R and RRO_IMM 2019-01-15 17:54:50 -03:00
ReinUsesLisp
5e6a0a08c1 shader_decode: Implement FMNMX_C, FMNMX_R and FMNMX_IMM 2019-01-15 17:54:50 -03:00
ReinUsesLisp
964ddeeb90 shader_decode: Implement MUFU 2019-01-15 17:54:50 -03:00
ReinUsesLisp
4ccaa1402d shader_decode: Implement FADD_C, FADD_R and FADD_IMM 2019-01-15 17:54:50 -03:00
ReinUsesLisp
7c192ec43f shader_decode: Implement FMUL_C, FMUL_R and FMUL_IMM 2019-01-15 17:54:50 -03:00
ReinUsesLisp
4c70d5b8eb shader_decode: Implement MOV_C and MOV_R 2019-01-15 17:54:50 -03:00
ReinUsesLisp
a4f052f6b3 video_core: Replace gl_shader_decompiler 2019-01-15 17:54:50 -03:00
ReinUsesLisp
0c6fb456e0 glsl_decompiler: Implementation 2019-01-15 17:54:50 -03:00
ReinUsesLisp
fbc67a0563 shader_ir: Add condition code helper 2019-01-15 17:54:50 -03:00
ReinUsesLisp
a58abbcfc4 shader_ir: Add predicate combiner helper 2019-01-15 17:54:49 -03:00
ReinUsesLisp
bf07272695 shader_ir: Add comparison helpers 2019-01-15 17:54:49 -03:00
ReinUsesLisp
60f044df56 shader_ir: Add half float helpers 2019-01-15 17:54:49 -03:00
ReinUsesLisp
e3c55e31d7 shader_ir: Add integer helpers 2019-01-15 17:54:49 -03:00
ReinUsesLisp
833d0806f9 shader_ir: Add float helpers 2019-01-15 17:54:49 -03:00
ReinUsesLisp
6b9eea3fe5 shader_ir: Add setters 2019-01-15 17:54:49 -03:00
ReinUsesLisp
12a95ff453 shader_ir: Add local memory getters 2019-01-15 17:54:49 -03:00
ReinUsesLisp
2f87fd060d shader_ir: Add internal flag getters 2019-01-15 17:54:49 -03:00
ReinUsesLisp
15f431f0cb shader_ir: Add attribute getters 2019-01-15 17:54:49 -03:00
ReinUsesLisp
864e8f55cf shader_ir: Add constant buffer getters 2019-01-15 17:54:49 -03:00
ReinUsesLisp
5e639bfcf6 shader_ir: Add register getter 2019-01-15 17:54:49 -03:00
ReinUsesLisp
4aaa2192b9 shader_ir: Add immediate node constructors 2019-01-15 17:54:49 -03:00
ReinUsesLisp
15a0e1481d shader_ir: Initial implementation 2019-01-15 17:54:49 -03:00
ReinUsesLisp
294df41b86 shader_bytecode: Fixup encoding 2019-01-15 17:54:49 -03:00
ReinUsesLisp
a0c8c16d07 shader_header: Make local memory size getter constant 2019-01-15 17:54:49 -03:00
Hexagon12
7c6bb8c17f Merge pull request #2020 from otaviopace/remove-spaces
audio_core: remove unnecessary spaces on comments
2019-01-14 16:49:37 +02:00
Otávio Pace
215ca770df audio_core: remove unnecessary spaces on comments 2019-01-14 00:22:05 -02:00
bunnei
bc879ae880 Merge pull request #1848 from FreddyFunk/QJsonArray
game_list: Remove a reference of a reference
2019-01-12 02:01:13 -05:00
bunnei
c9ef8b0af1 Merge pull request #1959 from DarkLordZach/custom-rtc
settings: Add support for setting the RTC manually
2019-01-10 17:05:21 -05:00
bunnei
83e8ad2331 Merge pull request #1939 from DarkLordZach/web-applet
applets: Implement HLE web browser applet (LibAppletOff)
2019-01-10 17:04:38 -05:00
bunnei
912f2a520a Merge pull request #2010 from ReinUsesLisp/gmem
gl_global_cache: Add dummy global cache manager
2019-01-08 16:44:53 -05:00
ReinUsesLisp
3121408a90 gl_global_cache: Add dummy global cache manager 2019-01-08 17:47:45 -03:00
Zach Hilman
ac7d8983eb settings: Fix comment structure 2019-01-07 19:40:28 -05:00
Zach Hilman
05dbb47af5 settings: Use std::chrono::seconds instead of s64 for RTC 2019-01-07 19:19:40 -05:00
Zach Hilman
dbb1eb9c29 time: Use custom RTC settings if applicable for game 2019-01-07 19:19:40 -05:00
Zach Hilman
21f1b2889d core: Set custom RTC differential on game boot 2019-01-07 19:19:40 -05:00
Zach Hilman
26c9f12271 qt: Provide UI to edit custom RTC settings 2019-01-07 19:19:40 -05:00
Zach Hilman
c6016856d8 settings: Add custom RTC settings
Stored as signed seconds since epoch.
2019-01-07 19:18:45 -05:00
ReinUsesLisp
19cf995225 gl_rasterizer: Skip framebuffer configuration if rendertargets have not been changed 2019-01-07 16:23:23 -03:00
bunnei
23ebd4920e Merge pull request #1999 from ReinUsesLisp/dirty-shader
gl_shader_cache: Use dirty flags for shaders
2019-01-07 14:22:30 -05:00
ReinUsesLisp
b683e41fca gl_rasterizer_cache: Use dirty flags for the depth buffer 2019-01-07 16:22:28 -03:00
ReinUsesLisp
179ee963db gl_rasterizer_cache: Use dirty flags for color buffers 2019-01-07 16:20:39 -03:00
ReinUsesLisp
0ab17ab406 gl_shader_cache: Use dirty flags for shaders 2019-01-07 16:13:12 -03:00
bunnei
17a68e5ebe Merge pull request #1989 from lioncash/set
service/vi: Unstub IApplicationDisplayService's SetLayerScalingMode
2019-01-07 12:59:33 -05:00
bunnei
e04d75f44c Merge pull request #1992 from DarkLordZach/move-profile-manager-ui
qt: Move profile manager to own UI tab
2019-01-07 11:41:37 -05:00
bunnei
37ac1bb576 Merge pull request #1990 from ReinUsesLisp/copy-surface-stream-copy
gl_rasterizer_cache: Use GL_STREAM_COPY for PBOs
2019-01-07 11:34:05 -05:00
Zach Hilman
2378ecd0e8 build: Copy web engine resources to correct location 2019-01-05 15:27:15 -05:00
ReinUsesLisp
fc8a8789da gl_rasterizer_cache: Use GL_STREAM_COPY for PBOs
Since the data is doing the path CPU -> GPU -> GPU copy is the most
approximate hint. Using GL_STREAM_DRAW generated a performance warning
on Nvidia's stack. Changing this hint removed the warning.
2019-01-05 02:27:55 -03:00
Lioncash
9e8737b535 service/vi: Correct scaling mode conversions
These values are not equivalent, based off RE. The internal value is put
into a lookup table with the following values:

[3, 0, 1, 2, 4]

So the values absolutely do not map 1:1 like the comment was indicating.
2019-01-04 21:45:18 -05:00
Lioncash
56e51da1d9 service/vi: Factor out scaling mode conversions from the IPC function itself
Avoids entangling the IPC buffer appending with the actual operation of
converting the scaling values over. This also inserts the proper error
handling for invalid scaling values.
2019-01-04 21:45:18 -05:00
Lioncash
40aa1ea9f9 service/vi: Unstub IApplicationDisplayService' SetLayerScalingMode()
This appears to only check if the scaling mode can actually be
handled, rather than actually setting the scaling mode for the layer.

This implements the same error handling performed on the passed in
values.
2019-01-04 21:45:14 -05:00
Zach Hilman
54d7b664da qt: Move profile manager to own UI tab 2019-01-04 17:32:13 -05:00
Zach Hilman
0f887daa72 build: Copy QtWebEngineProcess[d].exe to release dir on windows 2019-01-04 10:34:29 -05:00
Zach Hilman
15501477e7 Update Qt MSVC external to 5.12.0 2018-12-31 13:19:23 -05:00
Zach Hilman
0c5ede492f travis: Use correct package for linux Qt5WebEngine 2018-12-28 19:29:49 -05:00
Zach Hilman
cb930c4b5a web_browser: Add bounds checking to applet interface 2018-12-28 18:20:29 -05:00
Zach Hilman
ef4c4e239d cmake: Add USE_QT_WEB_ENGINE flag and update build system 2018-12-28 15:32:39 -05:00
Zach Hilman
45da3be40e main: Add main window integrations for QtWebBrowserApplet 2018-12-28 15:32:39 -05:00
Zach Hilman
e00e1fc755 qt: Implement Qt frontend to web browser
Using a custom reimplementation of QWebEngineView and an injector script.
2018-12-28 15:32:39 -05:00
Zach Hilman
32bfa92c71 core: Add getter and setter for WebBrowserApplet frontend 2018-12-28 15:32:39 -05:00
Zach Hilman
85a3368e6d frontend: Add frontend responder for web browser 2018-12-28 15:32:39 -05:00
Zach Hilman
69f622be36 applets: Implement LibAppletOff (Web) applet 2018-12-28 15:32:39 -05:00
Zach Hilman
4c20a39828 loader: Add accessor for Manual RomFS 2018-12-28 15:32:39 -05:00
Zach Hilman
621b25b6be hid: Make Hid service accessible and add GetPressState 2018-12-28 15:32:03 -05:00
Zach Hilman
abbcc8e61e romfs: Add SingleDiscard extraction type
Needed for manual RomFS extraction, as Full generates an extra directory and Truncated generates variable results.
2018-12-28 15:30:36 -05:00
Zach Hilman
94db6e5f3f am: Add size parameter to am:IStorage logging 2018-12-28 15:30:36 -05:00
FernandoS27
7b9c982d29 Add more info into textures' object labels 2018-12-09 17:22:29 -04:00
Frederic Laing
6d7514ccec game_list: Remove a reference of a reference 2018-12-03 19:26:36 +01:00
Cameron Cawley
e0b0947437 Add missing environment variables to travis-ci.env 2018-11-28 15:12:03 +00:00
333 changed files with 17659 additions and 8153 deletions

View File

@@ -1,16 +1,27 @@
<!--
Please keep in mind yuzu is EXPERIMENTAL SOFTWARE.
Please read the FAQ: https://yuzu-emu.org/wiki/faq/
Please read the FAQ:
https://yuzu-emu.org/wiki/faq/
When submitting an issue, please do the following:
THIS IS NOT A SUPPORT FORUM, FOR SUPPORT GO TO:
https://community.citra-emu.org/
- Provide the version (commit hash) of yuzu you are using.
- Provide sufficient detail for the issue to be reproduced.
- Provide:
If the FAQ does not answer your question, please go to:
https://community.citra-emu.org/
When submitting an issue, please check the following:
- You have read the above.
- You have provided the version (commit hash) of yuzu you are using.
- You have provided sufficient detail for the issue to be reproduced.
- You have provided system specs (if relevant).
- Please also provide:
- For any issues, a log file
- For crashes, a backtrace.
- For graphical issues, comparison screenshots with real hardware.
- For emulation inaccuracies, a test-case (if able).
-->

3
.gitmodules vendored
View File

@@ -37,3 +37,6 @@
[submodule "discord-rpc"]
path = externals/discord-rpc
url = https://github.com/discordapp/discord-rpc.git
[submodule "Vulkan-Headers"]
path = externals/Vulkan-Headers
url = https://github.com/KhronosGroup/Vulkan-Headers.git

View File

@@ -24,7 +24,7 @@ matrix:
- os: osx
env: NAME="macos build"
sudo: false
osx_image: xcode10
osx_image: xcode10.1
install: "./.travis/macos/deps.sh"
script: "./.travis/macos/build.sh"
after_success: "./.travis/macos/upload.sh"

View File

@@ -6,6 +6,8 @@ TRAVIS_BRANCH
TRAVIS_BUILD_ID
TRAVIS_BUILD_NUMBER
TRAVIS_COMMIT
TRAVIS_COMMIT_RANGE
TRAVIS_EVENT_TYPE
TRAVIS_JOB_ID
TRAVIS_JOB_NUMBER
TRAVIS_REPO_SLUG

View File

@@ -1,12 +1,12 @@
#!/bin/bash -ex
apt-get update
apt-get install --no-install-recommends -y build-essential git libqt5opengl5-dev libsdl2-dev libssl-dev python qtbase5-dev wget cmake ninja-build ccache
apt-get install --no-install-recommends -y build-essential git libqt5opengl5-dev libsdl2-dev libssl-dev python qtbase5-dev qtwebengine5-dev wget cmake ninja-build ccache
cd /yuzu
mkdir build && cd build
cmake .. -DYUZU_USE_BUNDLED_UNICORN=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON -G Ninja
cmake .. -DYUZU_USE_BUNDLED_UNICORN=ON -DYUZU_USE_QT_WEB_ENGINE=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON -G Ninja
ninja
ccache -s

View File

@@ -2,14 +2,14 @@
set -o pipefail
export MACOSX_DEPLOYMENT_TARGET=10.13
export MACOSX_DEPLOYMENT_TARGET=10.14
export Qt5_DIR=$(brew --prefix)/opt/qt5
export UNICORNDIR=$(pwd)/externals/unicorn
export PATH="/usr/local/opt/ccache/libexec:$PATH"
mkdir build && cd build
cmake --version
cmake .. -DYUZU_USE_BUNDLED_UNICORN=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DUSE_DISCORD_PRESENCE=ON
cmake .. -DYUZU_USE_BUNDLED_UNICORN=ON -DYUZU_USE_QT_WEB_ENGINE=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DUSE_DISCORD_PRESENCE=ON
make -j4
ccache -s

View File

@@ -19,8 +19,12 @@ option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)
option(YUZU_USE_BUNDLED_UNICORN "Build/Download bundled Unicorn" ON)
option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF)
option(ENABLE_CUBEB "Enables the cubeb audio backend" ON)
option(ENABLE_VULKAN "Enables Vulkan backend" ON)
option(USE_DISCORD_PRESENCE "Enables Discord Rich Presence" OFF)
if(NOT EXISTS ${PROJECT_SOURCE_DIR}/.git/hooks/pre-commit)
@@ -302,7 +306,7 @@ endif()
if (ENABLE_QT)
if (YUZU_USE_BUNDLED_QT)
if ((MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1920) AND ARCHITECTURE_x86_64)
set(QT_VER qt-5.10.0-msvc2015_64)
set(QT_VER qt-5.12.0-msvc2017_64)
else()
message(FATAL_ERROR "No bundled Qt binaries for your toolchain. Disable YUZU_USE_BUNDLED_QT and provide your own.")
endif()
@@ -319,6 +323,10 @@ if (ENABLE_QT)
endif()
find_package(Qt5 REQUIRED COMPONENTS Widgets OpenGL ${QT_PREFIX_HINT})
if (YUZU_USE_QT_WEB_ENGINE)
find_package(Qt5 REQUIRED COMPONENTS WebEngineCore WebEngineWidgets ${QT_PREFIX_HINT})
endif ()
endif()
# Platform-specific library requirements
@@ -413,19 +421,6 @@ function(create_target_directory_groups target_name)
endforeach()
endfunction()
# Gets a UTC timstamp and sets the provided variable to it
function(get_timestamp _var)
string(TIMESTAMP timestamp UTC)
set(${_var} "${timestamp}" PARENT_SCOPE)
endfunction()
# generate git/build information
include(GetGitRevisionDescription)
get_git_head_revision(GIT_REF_SPEC GIT_REV)
git_describe(GIT_DESC --always --long --dirty)
git_branch_name(GIT_BRANCH)
get_timestamp(BUILD_DATE)
enable_testing()
add_subdirectory(externals)
add_subdirectory(src)

View File

@@ -5,6 +5,7 @@ function(copy_yuzu_Qt5_deps target_dir)
set(Qt5_PLATFORMS_DIR "${Qt5_DIR}/../../../plugins/platforms/")
set(Qt5_STYLES_DIR "${Qt5_DIR}/../../../plugins/styles/")
set(Qt5_IMAGEFORMATS_DIR "${Qt5_DIR}/../../../plugins/imageformats/")
set(Qt5_RESOURCES_DIR "${Qt5_DIR}/../../../resources/")
set(PLATFORMS ${DLL_DEST}platforms/)
set(STYLES ${DLL_DEST}styles/)
set(IMAGEFORMATS ${DLL_DEST}imageformats/)
@@ -17,7 +18,35 @@ function(copy_yuzu_Qt5_deps target_dir)
Qt5OpenGL$<$<CONFIG:Debug>:d>.*
Qt5Widgets$<$<CONFIG:Debug>:d>.*
)
if (YUZU_USE_QT_WEB_ENGINE)
windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST}
Qt5Network$<$<CONFIG:Debug>:d>.*
Qt5Positioning$<$<CONFIG:Debug>:d>.*
Qt5PrintSupport$<$<CONFIG:Debug>:d>.*
Qt5Qml$<$<CONFIG:Debug>:d>.*
Qt5Quick$<$<CONFIG:Debug>:d>.*
Qt5QuickWidgets$<$<CONFIG:Debug>:d>.*
Qt5WebChannel$<$<CONFIG:Debug>:d>.*
Qt5WebEngine$<$<CONFIG:Debug>:d>.*
Qt5WebEngineCore$<$<CONFIG:Debug>:d>.*
Qt5WebEngineWidgets$<$<CONFIG:Debug>:d>.*
QtWebEngineProcess$<$<CONFIG:Debug>:d>.*
)
windows_copy_files(${target_dir} ${Qt5_RESOURCES_DIR} ${DLL_DEST}
qtwebengine_resources.pak
qtwebengine_devtools_resources.pak
qtwebengine_resources_100p.pak
qtwebengine_resources_200p.pak
icudtl.dat
)
endif ()
windows_copy_files(yuzu ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$<CONFIG:Debug>:d>.*)
windows_copy_files(yuzu ${Qt5_STYLES_DIR} ${STYLES} qwindowsvistastyle$<$<CONFIG:Debug>:d>.*)
windows_copy_files(yuzu ${Qt5_IMAGEFORMATS_DIR} ${IMAGEFORMATS} qjpeg$<$<CONFIG:Debug>:d>.*)
windows_copy_files(yuzu ${Qt5_IMAGEFORMATS_DIR} ${IMAGEFORMATS}
qjpeg$<$<CONFIG:Debug>:d>.*
qgif$<$<CONFIG:Debug>:d>.*
)
endfunction(copy_yuzu_Qt5_deps)

View File

@@ -0,0 +1,95 @@
# Gets a UTC timstamp and sets the provided variable to it
function(get_timestamp _var)
string(TIMESTAMP timestamp UTC)
set(${_var} "${timestamp}" PARENT_SCOPE)
endfunction()
list(APPEND CMAKE_MODULE_PATH "${SRC_DIR}/externals/cmake-modules")
# generate git/build information
include(GetGitRevisionDescription)
get_git_head_revision(GIT_REF_SPEC GIT_REV)
git_describe(GIT_DESC --always --long --dirty)
git_branch_name(GIT_BRANCH)
get_timestamp(BUILD_DATE)
# Generate cpp with Git revision from template
# Also if this is a CI build, add the build name (ie: Nightly, Canary) to the scm_rev file as well
set(REPO_NAME "")
set(BUILD_VERSION "0")
if (BUILD_REPOSITORY)
# regex capture the string nightly or canary into CMAKE_MATCH_1
string(REGEX MATCH "yuzu-emu/yuzu-?(.*)" OUTVAR ${BUILD_REPOSITORY})
if (${CMAKE_MATCH_COUNT} GREATER 0)
# capitalize the first letter of each word in the repo name.
string(REPLACE "-" ";" REPO_NAME_LIST ${CMAKE_MATCH_1})
foreach(WORD ${REPO_NAME_LIST})
string(SUBSTRING ${WORD} 0 1 FIRST_LETTER)
string(SUBSTRING ${WORD} 1 -1 REMAINDER)
string(TOUPPER ${FIRST_LETTER} FIRST_LETTER)
set(REPO_NAME "${REPO_NAME}${FIRST_LETTER}${REMAINDER}")
endforeach()
if (BUILD_TAG)
string(REGEX MATCH "${CMAKE_MATCH_1}-([0-9]+)" OUTVAR ${BUILD_TAG})
if (${CMAKE_MATCH_COUNT} GREATER 0)
set(BUILD_VERSION ${CMAKE_MATCH_1})
endif()
if (BUILD_VERSION)
# This leaves a trailing space on the last word, but we actually want that
# because of how it's styled in the title bar.
set(BUILD_FULLNAME "${REPO_NAME} ${BUILD_VERSION} ")
else()
set(BUILD_FULLNAME "")
endif()
endif()
endif()
endif()
# The variable SRC_DIR must be passed into the script (since it uses the current build directory for all values of CMAKE_*_DIR)
set(VIDEO_CORE "${SRC_DIR}/src/video_core")
set(HASH_FILES
"${VIDEO_CORE}/renderer_opengl/gl_shader_cache.cpp"
"${VIDEO_CORE}/renderer_opengl/gl_shader_cache.h"
"${VIDEO_CORE}/renderer_opengl/gl_shader_decompiler.cpp"
"${VIDEO_CORE}/renderer_opengl/gl_shader_decompiler.h"
"${VIDEO_CORE}/renderer_opengl/gl_shader_disk_cache.cpp"
"${VIDEO_CORE}/renderer_opengl/gl_shader_disk_cache.h"
"${VIDEO_CORE}/renderer_opengl/gl_shader_gen.cpp"
"${VIDEO_CORE}/renderer_opengl/gl_shader_gen.h"
"${VIDEO_CORE}/shader/decode/arithmetic.cpp"
"${VIDEO_CORE}/shader/decode/arithmetic_half.cpp"
"${VIDEO_CORE}/shader/decode/arithmetic_half_immediate.cpp"
"${VIDEO_CORE}/shader/decode/arithmetic_immediate.cpp"
"${VIDEO_CORE}/shader/decode/arithmetic_integer.cpp"
"${VIDEO_CORE}/shader/decode/arithmetic_integer_immediate.cpp"
"${VIDEO_CORE}/shader/decode/bfe.cpp"
"${VIDEO_CORE}/shader/decode/bfi.cpp"
"${VIDEO_CORE}/shader/decode/conversion.cpp"
"${VIDEO_CORE}/shader/decode/ffma.cpp"
"${VIDEO_CORE}/shader/decode/float_set.cpp"
"${VIDEO_CORE}/shader/decode/float_set_predicate.cpp"
"${VIDEO_CORE}/shader/decode/half_set.cpp"
"${VIDEO_CORE}/shader/decode/half_set_predicate.cpp"
"${VIDEO_CORE}/shader/decode/hfma2.cpp"
"${VIDEO_CORE}/shader/decode/integer_set.cpp"
"${VIDEO_CORE}/shader/decode/integer_set_predicate.cpp"
"${VIDEO_CORE}/shader/decode/memory.cpp"
"${VIDEO_CORE}/shader/decode/texture.cpp"
"${VIDEO_CORE}/shader/decode/other.cpp"
"${VIDEO_CORE}/shader/decode/predicate_set_predicate.cpp"
"${VIDEO_CORE}/shader/decode/predicate_set_register.cpp"
"${VIDEO_CORE}/shader/decode/register_set_predicate.cpp"
"${VIDEO_CORE}/shader/decode/shift.cpp"
"${VIDEO_CORE}/shader/decode/video.cpp"
"${VIDEO_CORE}/shader/decode/xmad.cpp"
"${VIDEO_CORE}/shader/decode.cpp"
"${VIDEO_CORE}/shader/shader_ir.cpp"
"${VIDEO_CORE}/shader/shader_ir.h"
"${VIDEO_CORE}/shader/track.cpp"
)
set(COMBINED "")
foreach (F IN LISTS HASH_FILES)
file(READ ${F} TMP)
set(COMBINED "${COMBINED}${TMP}")
endforeach()
string(MD5 SHADER_CACHE_VERSION "${COMBINED}")
configure_file("${SRC_DIR}/src/common/scm_rev.cpp.in" "scm_rev.cpp" @ONLY)

View File

@@ -7,7 +7,7 @@ yuzu is an experimental open-source emulator for the Nintendo Switch from the cr
It is written in C++ with portability in mind, with builds actively maintained for Windows, Linux and macOS. The emulator is currently only useful for homebrew development and research purposes.
yuzu only emulates a subset of Switch hardware and therefore is generally only useful for running/debugging homebrew applications. At this time, yuzu cannot play any commercial games without major problems. yuzu can boot some games, to varying degrees of success, but does not implement any of the necessary GPU features to render 3D graphics.
yuzu only emulates a subset of Switch hardware and therefore is generally only useful for running/debugging homebrew applications. At this time, yuzu cannot play any commercial games without major problems. yuzu can boot some games, to varying degrees of success.
yuzu is licensed under the GPLv2 (or any later version). Refer to the license.txt file included.

View File

@@ -42,7 +42,7 @@ before_build:
$COMPAT = if ($env:ENABLE_COMPATIBILITY_REPORTING -eq $null) {0} else {$env:ENABLE_COMPATIBILITY_REPORTING}
if ($env:BUILD_TYPE -eq 'msvc') {
# redirect stderr and change the exit code to prevent powershell from cancelling the build if cmake prints a warning
cmd /C 'cmake -G "Visual Studio 15 2017 Win64" -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_BUNDLED_UNICORN=1 -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DUSE_DISCORD_PRESENCE=ON .. 2>&1 && exit 0'
cmd /C 'cmake -G "Visual Studio 15 2017 Win64" -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_BUNDLED_UNICORN=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DUSE_DISCORD_PRESENCE=ON .. 2>&1 && exit 0'
} else {
C:\msys64\usr\bin\bash.exe -lc "cmake -G 'MSYS Makefiles' -DYUZU_BUILD_UNICORN=1 -DCMAKE_BUILD_TYPE=Release -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DUSE_DISCORD_PRESENCE=ON .. 2>&1"
}
@@ -94,6 +94,7 @@ after_build:
Copy-Item "$BUILD_DIR\*" -Destination $RELEASE_DIST -Recurse
rm "$RELEASE_DIST\*.exe"
Get-ChildItem "$BUILD_DIR" -Recurse -Filter "yuzu*.exe" | Copy-Item -destination $RELEASE_DIST
Get-ChildItem "$BUILD_DIR" -Recurse -Filter "QtWebEngineProcess*.exe" | Copy-Item -destination $RELEASE_DIST
Copy-Item .\license.txt -Destination $RELEASE_DIST
Copy-Item .\README.md -Destination $RELEASE_DIST
7z a -tzip $MSVC_BUILD_ZIP $RELEASE_DIST\*

1
externals/Vulkan-Headers vendored Submodule

View File

@@ -26,14 +26,15 @@ static Stream::Format ChannelsToStreamFormat(u32 num_channels) {
return {};
}
StreamPtr AudioOut::OpenStream(u32 sample_rate, u32 num_channels, std::string&& name,
StreamPtr AudioOut::OpenStream(Core::Timing::CoreTiming& core_timing, u32 sample_rate,
u32 num_channels, std::string&& name,
Stream::ReleaseCallback&& release_callback) {
if (!sink) {
sink = CreateSinkFromID(Settings::values.sink_id, Settings::values.audio_device_id);
}
return std::make_shared<Stream>(
sample_rate, ChannelsToStreamFormat(num_channels), std::move(release_callback),
core_timing, sample_rate, ChannelsToStreamFormat(num_channels), std::move(release_callback),
sink->AcquireSinkStream(sample_rate, num_channels, name), std::move(name));
}

View File

@@ -13,6 +13,10 @@
#include "audio_core/stream.h"
#include "common/common_types.h"
namespace Core::Timing {
class CoreTiming;
}
namespace AudioCore {
/**
@@ -21,8 +25,8 @@ namespace AudioCore {
class AudioOut {
public:
/// Opens a new audio stream
StreamPtr OpenStream(u32 sample_rate, u32 num_channels, std::string&& name,
Stream::ReleaseCallback&& release_callback);
StreamPtr OpenStream(Core::Timing::CoreTiming& core_timing, u32 sample_rate, u32 num_channels,
std::string&& name, Stream::ReleaseCallback&& release_callback);
/// Returns a vector of recently released buffers specified by tag for the specified stream
std::vector<Buffer::Tag> GetTagsAndReleaseBuffers(StreamPtr stream, std::size_t max_count);

View File

@@ -8,6 +8,7 @@
#include "audio_core/codec.h"
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/kernel/writable_event.h"
#include "core/memory.h"
@@ -71,14 +72,14 @@ private:
EffectOutStatus out_status{};
EffectInStatus info{};
};
AudioRenderer::AudioRenderer(AudioRendererParameter params,
AudioRenderer::AudioRenderer(Core::Timing::CoreTiming& core_timing, AudioRendererParameter params,
Kernel::SharedPtr<Kernel::WritableEvent> buffer_event)
: worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count),
effects(params.effect_count) {
audio_out = std::make_unique<AudioCore::AudioOut>();
stream = audio_out->OpenStream(STREAM_SAMPLE_RATE, STREAM_NUM_CHANNELS, "AudioRenderer",
[=]() { buffer_event->Signal(); });
stream = audio_out->OpenStream(core_timing, STREAM_SAMPLE_RATE, STREAM_NUM_CHANNELS,
"AudioRenderer", [=]() { buffer_event->Signal(); });
audio_out->StartStream(stream);
QueueMixedBuffer(0);

View File

@@ -14,6 +14,10 @@
#include "common/swap.h"
#include "core/hle/kernel/object.h"
namespace Core::Timing {
class CoreTiming;
}
namespace Kernel {
class WritableEvent;
}
@@ -42,16 +46,18 @@ struct AudioRendererParameter {
u32_le sample_rate;
u32_le sample_count;
u32_le mix_buffer_count;
u32_le unknown_c;
u32_le submix_count;
u32_le voice_count;
u32_le sink_count;
u32_le effect_count;
u32_le unknown_1c;
u8 unknown_20;
INSERT_PADDING_BYTES(3);
u32_le performance_frame_count;
u8 is_voice_drop_enabled;
u8 unknown_21;
u8 unknown_22;
u8 execution_mode;
u32_le splitter_count;
u32_le unknown_2c;
INSERT_PADDING_WORDS(1);
u32_le num_splitter_send_channels;
u32_le unknown_30;
u32_le revision;
};
static_assert(sizeof(AudioRendererParameter) == 52, "AudioRendererParameter is an invalid size");
@@ -208,7 +214,7 @@ static_assert(sizeof(UpdateDataHeader) == 0x40, "UpdateDataHeader has wrong size
class AudioRenderer {
public:
AudioRenderer(AudioRendererParameter params,
AudioRenderer(Core::Timing::CoreTiming& core_timing, AudioRendererParameter params,
Kernel::SharedPtr<Kernel::WritableEvent> buffer_event);
~AudioRenderer();

View File

@@ -21,7 +21,7 @@ public:
Buffer(Tag tag, std::vector<s16>&& samples) : tag{tag}, samples{std::move(samples)} {}
/// Returns the raw audio data for the buffer
std::vector<s16>& Samples() {
std::vector<s16>& GetSamples() {
return samples;
}

View File

@@ -68,8 +68,8 @@ std::vector<s16> DecodeADPCM(const u8* const data, std::size_t size, const ADPCM
}
}
state.yn1 = yn1;
state.yn2 = yn2;
state.yn1 = static_cast<s16>(yn1);
state.yn2 = static_cast<s16>(yn2);
return ret;
}

View File

@@ -12,6 +12,10 @@
#include "common/ring_buffer.h"
#include "core/settings.h"
#ifdef _WIN32
#include <objbase.h>
#endif
namespace AudioCore {
class CubebSinkStream final : public SinkStream {
@@ -46,7 +50,7 @@ public:
}
}
~CubebSinkStream() {
~CubebSinkStream() override {
if (!ctx) {
return;
}
@@ -75,11 +79,11 @@ public:
queue.Push(samples);
}
std::size_t SamplesInQueue(u32 num_channels) const override {
std::size_t SamplesInQueue(u32 channel_count) const override {
if (!ctx)
return 0;
return queue.Size() / num_channels;
return queue.Size() / channel_count;
}
void Flush() override {
@@ -98,7 +102,7 @@ private:
u32 num_channels{};
Common::RingBuffer<s16, 0x10000> queue;
std::array<s16, 2> last_frame;
std::array<s16, 2> last_frame{};
std::atomic<bool> should_flush{};
TimeStretcher time_stretch;
@@ -108,6 +112,11 @@ private:
};
CubebSink::CubebSink(std::string_view target_device_name) {
// Cubeb requires COM to be initialized on the thread calling cubeb_init on Windows
#ifdef _WIN32
com_init_result = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
#endif
if (cubeb_init(&ctx, "yuzu", nullptr) != CUBEB_OK) {
LOG_CRITICAL(Audio_Sink, "cubeb_init failed");
return;
@@ -142,6 +151,12 @@ CubebSink::~CubebSink() {
}
cubeb_destroy(ctx);
#ifdef _WIN32
if (SUCCEEDED(com_init_result)) {
CoUninitialize();
}
#endif
}
SinkStream& CubebSink::AcquireSinkStream(u32 sample_rate, u32 num_channels,

View File

@@ -25,6 +25,10 @@ private:
cubeb* ctx{};
cubeb_devid output_device{};
std::vector<SinkStreamPtr> sink_streams;
#ifdef _WIN32
u32 com_init_result = 0;
#endif
};
std::vector<std::string> ListCubebSinkDevices();

View File

@@ -32,12 +32,12 @@ u32 Stream::GetNumChannels() const {
return {};
}
Stream::Stream(u32 sample_rate, Format format, ReleaseCallback&& release_callback,
SinkStream& sink_stream, std::string&& name_)
Stream::Stream(Core::Timing::CoreTiming& core_timing, u32 sample_rate, Format format,
ReleaseCallback&& release_callback, SinkStream& sink_stream, std::string&& name_)
: sample_rate{sample_rate}, format{format}, release_callback{std::move(release_callback)},
sink_stream{sink_stream}, name{std::move(name_)} {
sink_stream{sink_stream}, core_timing{core_timing}, name{std::move(name_)} {
release_event = CoreTiming::RegisterEvent(
release_event = core_timing.RegisterEvent(
name, [this](u64 userdata, int cycles_late) { ReleaseActiveBuffer(); });
}
@@ -57,7 +57,7 @@ Stream::State Stream::GetState() const {
s64 Stream::GetBufferReleaseCycles(const Buffer& buffer) const {
const std::size_t num_samples{buffer.GetSamples().size() / GetNumChannels()};
return CoreTiming::usToCycles((static_cast<u64>(num_samples) * 1000000) / sample_rate);
return Core::Timing::usToCycles((static_cast<u64>(num_samples) * 1000000) / sample_rate);
}
static void VolumeAdjustSamples(std::vector<s16>& samples) {
@@ -68,7 +68,7 @@ static void VolumeAdjustSamples(std::vector<s16>& samples) {
}
// Implementation of a volume slider with a dynamic range of 60 dB
const float volume_scale_factor{std::exp(6.90775f * volume) * 0.001f};
const float volume_scale_factor = volume == 0 ? 0 : std::exp(6.90775f * volume) * 0.001f;
for (auto& sample : samples) {
sample = static_cast<s16>(sample * volume_scale_factor);
}
@@ -95,11 +95,11 @@ void Stream::PlayNextBuffer() {
active_buffer = queued_buffers.front();
queued_buffers.pop();
VolumeAdjustSamples(active_buffer->Samples());
VolumeAdjustSamples(active_buffer->GetSamples());
sink_stream.EnqueueSamples(GetNumChannels(), active_buffer->GetSamples());
CoreTiming::ScheduleEventThreadsafe(GetBufferReleaseCycles(*active_buffer), release_event, {});
core_timing.ScheduleEventThreadsafe(GetBufferReleaseCycles(*active_buffer), release_event, {});
}
void Stream::ReleaseActiveBuffer() {

View File

@@ -13,9 +13,10 @@
#include "audio_core/buffer.h"
#include "common/common_types.h"
namespace CoreTiming {
namespace Core::Timing {
class CoreTiming;
struct EventType;
}
} // namespace Core::Timing
namespace AudioCore {
@@ -42,8 +43,8 @@ public:
/// Callback function type, used to change guest state on a buffer being released
using ReleaseCallback = std::function<void()>;
Stream(u32 sample_rate, Format format, ReleaseCallback&& release_callback,
SinkStream& sink_stream, std::string&& name_);
Stream(Core::Timing::CoreTiming& core_timing, u32 sample_rate, Format format,
ReleaseCallback&& release_callback, SinkStream& sink_stream, std::string&& name_);
/// Plays the audio stream
void Play();
@@ -91,16 +92,17 @@ private:
/// Gets the number of core cycles when the specified buffer will be released
s64 GetBufferReleaseCycles(const Buffer& buffer) const;
u32 sample_rate; ///< Sample rate of the stream
Format format; ///< Format of the stream
ReleaseCallback release_callback; ///< Buffer release callback for the stream
State state{State::Stopped}; ///< Playback state of the stream
CoreTiming::EventType* release_event{}; ///< Core timing release event for the stream
BufferPtr active_buffer; ///< Actively playing buffer in the stream
std::queue<BufferPtr> queued_buffers; ///< Buffers queued to be played in the stream
std::queue<BufferPtr> released_buffers; ///< Buffers recently released from the stream
SinkStream& sink_stream; ///< Output sink for the stream
std::string name; ///< Name of the stream, must be unique
u32 sample_rate; ///< Sample rate of the stream
Format format; ///< Format of the stream
ReleaseCallback release_callback; ///< Buffer release callback for the stream
State state{State::Stopped}; ///< Playback state of the stream
Core::Timing::EventType* release_event{}; ///< Core timing release event for the stream
BufferPtr active_buffer; ///< Actively playing buffer in the stream
std::queue<BufferPtr> queued_buffers; ///< Buffers queued to be played in the stream
std::queue<BufferPtr> released_buffers; ///< Buffers recently released from the stream
SinkStream& sink_stream; ///< Output sink for the stream
Core::Timing::CoreTiming& core_timing; ///< Core timing instance.
std::string name; ///< Name of the stream, must be unique
};
using StreamPtr = std::shared_ptr<Stream>;

View File

@@ -53,8 +53,8 @@ std::size_t TimeStretcher::Process(const s16* in, std::size_t num_in, s16* out,
const double lpf_gain = 1.0 - std::exp(-time_delta / lpf_time_scale);
m_stretch_ratio += lpf_gain * (current_ratio - m_stretch_ratio);
// Place a lower limit of 5% speed. When a game boots up, there will be
// many silence samples. These do not need to be timestretched.
// Place a lower limit of 5% speed. When a game boots up, there will be
// many silence samples. These do not need to be timestretched.
m_stretch_ratio = std::max(m_stretch_ratio, 0.05);
m_sound_touch.setTempo(m_stretch_ratio);

View File

@@ -1,42 +1,70 @@
# Generate cpp with Git revision from template
# Also if this is a CI build, add the build name (ie: Nightly, Canary) to the scm_rev file as well
set(REPO_NAME "")
set(BUILD_VERSION "0")
if ($ENV{CI})
if ($ENV{TRAVIS})
# Add a custom command to generate a new shader_cache_version hash when any of the following files change
# NOTE: This is an approximation of what files affect shader generation, its possible something else
# could affect the result, but much more unlikely than the following files. Keeping a list of files
# like this allows for much better caching since it doesn't force the user to recompile binary shaders every update
set(VIDEO_CORE "${CMAKE_SOURCE_DIR}/src/video_core")
if (DEFINED ENV{CI})
if (DEFINED ENV{TRAVIS})
set(BUILD_REPOSITORY $ENV{TRAVIS_REPO_SLUG})
set(BUILD_TAG $ENV{TRAVIS_TAG})
elseif($ENV{APPVEYOR})
elseif(DEFINED ENV{APPVEYOR})
set(BUILD_REPOSITORY $ENV{APPVEYOR_REPO_NAME})
set(BUILD_TAG $ENV{APPVEYOR_REPO_TAG_NAME})
endif()
# regex capture the string nightly or canary into CMAKE_MATCH_1
string(REGEX MATCH "yuzu-emu/yuzu-?(.*)" OUTVAR ${BUILD_REPOSITORY})
if (${CMAKE_MATCH_COUNT} GREATER 0)
# capitalize the first letter of each word in the repo name.
string(REPLACE "-" ";" REPO_NAME_LIST ${CMAKE_MATCH_1})
foreach(WORD ${REPO_NAME_LIST})
string(SUBSTRING ${WORD} 0 1 FIRST_LETTER)
string(SUBSTRING ${WORD} 1 -1 REMAINDER)
string(TOUPPER ${FIRST_LETTER} FIRST_LETTER)
set(REPO_NAME "${REPO_NAME}${FIRST_LETTER}${REMAINDER}")
endforeach()
if (BUILD_TAG)
string(REGEX MATCH "${CMAKE_MATCH_1}-([0-9]+)" OUTVAR ${BUILD_TAG})
if (${CMAKE_MATCH_COUNT} GREATER 0)
set(BUILD_VERSION ${CMAKE_MATCH_1})
endif()
if (BUILD_VERSION)
# This leaves a trailing space on the last word, but we actually want that
# because of how it's styled in the title bar.
set(BUILD_FULLNAME "${REPO_NAME} ${BUILD_VERSION} ")
else()
set(BUILD_FULLNAME "")
endif()
endif()
endif()
endif()
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.cpp.in" "${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.cpp" @ONLY)
add_custom_command(OUTPUT scm_rev.cpp
COMMAND ${CMAKE_COMMAND}
-DSRC_DIR="${CMAKE_SOURCE_DIR}"
-DBUILD_REPOSITORY="${BUILD_REPOSITORY}"
-DBUILD_TAG="${BUILD_TAG}"
-P "${CMAKE_SOURCE_DIR}/CMakeModules/GenerateSCMRev.cmake"
DEPENDS
# WARNING! It was too much work to try and make a common location for this list,
# so if you need to change it, please update CMakeModules/GenerateSCMRev.cmake as well
"${VIDEO_CORE}/renderer_opengl/gl_shader_cache.cpp"
"${VIDEO_CORE}/renderer_opengl/gl_shader_cache.h"
"${VIDEO_CORE}/renderer_opengl/gl_shader_decompiler.cpp"
"${VIDEO_CORE}/renderer_opengl/gl_shader_decompiler.h"
"${VIDEO_CORE}/renderer_opengl/gl_shader_disk_cache.cpp"
"${VIDEO_CORE}/renderer_opengl/gl_shader_disk_cache.h"
"${VIDEO_CORE}/renderer_opengl/gl_shader_gen.cpp"
"${VIDEO_CORE}/renderer_opengl/gl_shader_gen.h"
"${VIDEO_CORE}/shader/decode/arithmetic.cpp"
"${VIDEO_CORE}/shader/decode/arithmetic_half.cpp"
"${VIDEO_CORE}/shader/decode/arithmetic_half_immediate.cpp"
"${VIDEO_CORE}/shader/decode/arithmetic_immediate.cpp"
"${VIDEO_CORE}/shader/decode/arithmetic_integer.cpp"
"${VIDEO_CORE}/shader/decode/arithmetic_integer_immediate.cpp"
"${VIDEO_CORE}/shader/decode/bfe.cpp"
"${VIDEO_CORE}/shader/decode/bfi.cpp"
"${VIDEO_CORE}/shader/decode/conversion.cpp"
"${VIDEO_CORE}/shader/decode/ffma.cpp"
"${VIDEO_CORE}/shader/decode/float_set.cpp"
"${VIDEO_CORE}/shader/decode/float_set_predicate.cpp"
"${VIDEO_CORE}/shader/decode/half_set.cpp"
"${VIDEO_CORE}/shader/decode/half_set_predicate.cpp"
"${VIDEO_CORE}/shader/decode/hfma2.cpp"
"${VIDEO_CORE}/shader/decode/integer_set.cpp"
"${VIDEO_CORE}/shader/decode/integer_set_predicate.cpp"
"${VIDEO_CORE}/shader/decode/memory.cpp"
"${VIDEO_CORE}/shader/decode/texture.cpp"
"${VIDEO_CORE}/shader/decode/other.cpp"
"${VIDEO_CORE}/shader/decode/predicate_set_predicate.cpp"
"${VIDEO_CORE}/shader/decode/predicate_set_register.cpp"
"${VIDEO_CORE}/shader/decode/register_set_predicate.cpp"
"${VIDEO_CORE}/shader/decode/shift.cpp"
"${VIDEO_CORE}/shader/decode/video.cpp"
"${VIDEO_CORE}/shader/decode/xmad.cpp"
"${VIDEO_CORE}/shader/decode.cpp"
"${VIDEO_CORE}/shader/shader_ir.cpp"
"${VIDEO_CORE}/shader/shader_ir.h"
"${VIDEO_CORE}/shader/track.cpp"
# and also check that the scm_rev files haven't changed
"${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.cpp.in"
"${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.h"
# technically we should regenerate if the git version changed, but its not worth the effort imo
"${CMAKE_SOURCE_DIR}/CMakeModules/GenerateSCMRev.cmake"
)
add_library(common STATIC
alignment.h

View File

@@ -111,12 +111,6 @@
template <std::size_t Position, std::size_t Bits, typename T>
struct BitField {
private:
// We hide the copy assigment operator here, because the default copy
// assignment would copy the full storage value, rather than just the bits
// relevant to this particular bit field.
// We don't delete it because we want BitField to be trivially copyable.
constexpr BitField& operator=(const BitField&) = default;
// UnderlyingType is T for non-enum types and the underlying type of T if
// T is an enumeration. Note that T is wrapped within an enable_if in the
// former case to workaround compile errors which arise when using
@@ -163,9 +157,13 @@ public:
BitField(T val) = delete;
BitField& operator=(T val) = delete;
// Force default constructor to be created
// so that we can use this within unions
constexpr BitField() = default;
constexpr BitField() noexcept = default;
constexpr BitField(const BitField&) noexcept = default;
constexpr BitField& operator=(const BitField&) noexcept = default;
constexpr BitField(BitField&&) noexcept = default;
constexpr BitField& operator=(BitField&&) noexcept = default;
constexpr FORCE_INLINE operator T() const {
return Value();

View File

@@ -55,36 +55,36 @@ constexpr u8 Convert8To6(u8 value) {
/**
* Decode a color stored in RGBA8 format
* @param bytes Pointer to encoded source color
* @return Result color decoded as Math::Vec4<u8>
* @return Result color decoded as Common::Vec4<u8>
*/
inline Math::Vec4<u8> DecodeRGBA8(const u8* bytes) {
inline Common::Vec4<u8> DecodeRGBA8(const u8* bytes) {
return {bytes[3], bytes[2], bytes[1], bytes[0]};
}
/**
* Decode a color stored in RGB8 format
* @param bytes Pointer to encoded source color
* @return Result color decoded as Math::Vec4<u8>
* @return Result color decoded as Common::Vec4<u8>
*/
inline Math::Vec4<u8> DecodeRGB8(const u8* bytes) {
inline Common::Vec4<u8> DecodeRGB8(const u8* bytes) {
return {bytes[2], bytes[1], bytes[0], 255};
}
/**
* Decode a color stored in RG8 (aka HILO8) format
* @param bytes Pointer to encoded source color
* @return Result color decoded as Math::Vec4<u8>
* @return Result color decoded as Common::Vec4<u8>
*/
inline Math::Vec4<u8> DecodeRG8(const u8* bytes) {
inline Common::Vec4<u8> DecodeRG8(const u8* bytes) {
return {bytes[1], bytes[0], 0, 255};
}
/**
* Decode a color stored in RGB565 format
* @param bytes Pointer to encoded source color
* @return Result color decoded as Math::Vec4<u8>
* @return Result color decoded as Common::Vec4<u8>
*/
inline Math::Vec4<u8> DecodeRGB565(const u8* bytes) {
inline Common::Vec4<u8> DecodeRGB565(const u8* bytes) {
u16_le pixel;
std::memcpy(&pixel, bytes, sizeof(pixel));
return {Convert5To8((pixel >> 11) & 0x1F), Convert6To8((pixel >> 5) & 0x3F),
@@ -94,9 +94,9 @@ inline Math::Vec4<u8> DecodeRGB565(const u8* bytes) {
/**
* Decode a color stored in RGB5A1 format
* @param bytes Pointer to encoded source color
* @return Result color decoded as Math::Vec4<u8>
* @return Result color decoded as Common::Vec4<u8>
*/
inline Math::Vec4<u8> DecodeRGB5A1(const u8* bytes) {
inline Common::Vec4<u8> DecodeRGB5A1(const u8* bytes) {
u16_le pixel;
std::memcpy(&pixel, bytes, sizeof(pixel));
return {Convert5To8((pixel >> 11) & 0x1F), Convert5To8((pixel >> 6) & 0x1F),
@@ -106,9 +106,9 @@ inline Math::Vec4<u8> DecodeRGB5A1(const u8* bytes) {
/**
* Decode a color stored in RGBA4 format
* @param bytes Pointer to encoded source color
* @return Result color decoded as Math::Vec4<u8>
* @return Result color decoded as Common::Vec4<u8>
*/
inline Math::Vec4<u8> DecodeRGBA4(const u8* bytes) {
inline Common::Vec4<u8> DecodeRGBA4(const u8* bytes) {
u16_le pixel;
std::memcpy(&pixel, bytes, sizeof(pixel));
return {Convert4To8((pixel >> 12) & 0xF), Convert4To8((pixel >> 8) & 0xF),
@@ -138,9 +138,9 @@ inline u32 DecodeD24(const u8* bytes) {
/**
* Decode a depth value and a stencil value stored in D24S8 format
* @param bytes Pointer to encoded source values
* @return Resulting values stored as a Math::Vec2
* @return Resulting values stored as a Common::Vec2
*/
inline Math::Vec2<u32> DecodeD24S8(const u8* bytes) {
inline Common::Vec2<u32> DecodeD24S8(const u8* bytes) {
return {static_cast<u32>((bytes[2] << 16) | (bytes[1] << 8) | bytes[0]), bytes[3]};
}
@@ -149,7 +149,7 @@ inline Math::Vec2<u32> DecodeD24S8(const u8* bytes) {
* @param color Source color to encode
* @param bytes Destination pointer to store encoded color
*/
inline void EncodeRGBA8(const Math::Vec4<u8>& color, u8* bytes) {
inline void EncodeRGBA8(const Common::Vec4<u8>& color, u8* bytes) {
bytes[3] = color.r();
bytes[2] = color.g();
bytes[1] = color.b();
@@ -161,7 +161,7 @@ inline void EncodeRGBA8(const Math::Vec4<u8>& color, u8* bytes) {
* @param color Source color to encode
* @param bytes Destination pointer to store encoded color
*/
inline void EncodeRGB8(const Math::Vec4<u8>& color, u8* bytes) {
inline void EncodeRGB8(const Common::Vec4<u8>& color, u8* bytes) {
bytes[2] = color.r();
bytes[1] = color.g();
bytes[0] = color.b();
@@ -172,7 +172,7 @@ inline void EncodeRGB8(const Math::Vec4<u8>& color, u8* bytes) {
* @param color Source color to encode
* @param bytes Destination pointer to store encoded color
*/
inline void EncodeRG8(const Math::Vec4<u8>& color, u8* bytes) {
inline void EncodeRG8(const Common::Vec4<u8>& color, u8* bytes) {
bytes[1] = color.r();
bytes[0] = color.g();
}
@@ -181,7 +181,7 @@ inline void EncodeRG8(const Math::Vec4<u8>& color, u8* bytes) {
* @param color Source color to encode
* @param bytes Destination pointer to store encoded color
*/
inline void EncodeRGB565(const Math::Vec4<u8>& color, u8* bytes) {
inline void EncodeRGB565(const Common::Vec4<u8>& color, u8* bytes) {
const u16_le data =
(Convert8To5(color.r()) << 11) | (Convert8To6(color.g()) << 5) | Convert8To5(color.b());
@@ -193,7 +193,7 @@ inline void EncodeRGB565(const Math::Vec4<u8>& color, u8* bytes) {
* @param color Source color to encode
* @param bytes Destination pointer to store encoded color
*/
inline void EncodeRGB5A1(const Math::Vec4<u8>& color, u8* bytes) {
inline void EncodeRGB5A1(const Common::Vec4<u8>& color, u8* bytes) {
const u16_le data = (Convert8To5(color.r()) << 11) | (Convert8To5(color.g()) << 6) |
(Convert8To5(color.b()) << 1) | Convert8To1(color.a());
@@ -205,7 +205,7 @@ inline void EncodeRGB5A1(const Math::Vec4<u8>& color, u8* bytes) {
* @param color Source color to encode
* @param bytes Destination pointer to store encoded color
*/
inline void EncodeRGBA4(const Math::Vec4<u8>& color, u8* bytes) {
inline void EncodeRGBA4(const Common::Vec4<u8>& color, u8* bytes) {
const u16 data = (Convert8To4(color.r()) << 12) | (Convert8To4(color.g()) << 8) |
(Convert8To4(color.b()) << 4) | Convert8To4(color.a());

View File

@@ -35,6 +35,7 @@
#define KEYS_DIR "keys"
#define LOAD_DIR "load"
#define DUMP_DIR "dump"
#define SHADER_DIR "shader"
#define LOG_DIR "log"
// Filenames

View File

@@ -710,6 +710,7 @@ const std::string& GetUserPath(UserPath path, const std::string& new_path) {
paths.emplace(UserPath::NANDDir, user_path + NAND_DIR DIR_SEP);
paths.emplace(UserPath::LoadDir, user_path + LOAD_DIR DIR_SEP);
paths.emplace(UserPath::DumpDir, user_path + DUMP_DIR DIR_SEP);
paths.emplace(UserPath::ShaderDir, user_path + SHADER_DIR DIR_SEP);
paths.emplace(UserPath::SysDataDir, user_path + SYSDATA_DIR DIR_SEP);
paths.emplace(UserPath::KeysDir, user_path + KEYS_DIR DIR_SEP);
// TODO: Put the logs in a better location for each OS

View File

@@ -31,6 +31,7 @@ enum class UserPath {
SDMCDir,
LoadDir,
DumpDir,
ShaderDir,
SysDataDir,
UserDir,
};

View File

@@ -39,10 +39,10 @@ public:
Impl(Impl const&) = delete;
const Impl& operator=(Impl const&) = delete;
void PushEntry(Entry e) {
std::lock_guard<std::mutex> lock(message_mutex);
message_queue.Push(std::move(e));
message_cv.notify_one();
void PushEntry(Class log_class, Level log_level, const char* filename, unsigned int line_num,
const char* function, std::string message) {
message_queue.Push(
CreateEntry(log_class, log_level, filename, line_num, function, std::move(message)));
}
void AddBackend(std::unique_ptr<Backend> backend) {
@@ -86,15 +86,13 @@ private:
}
};
while (true) {
{
std::unique_lock<std::mutex> lock(message_mutex);
message_cv.wait(lock, [&] { return !running || message_queue.Pop(entry); });
}
if (!running) {
entry = message_queue.PopWait();
if (entry.final_entry) {
break;
}
write_logs(entry);
}
// Drain the logging queue. Only writes out up to MAX_LOGS_TO_WRITE to prevent a case
// where a system is repeatedly spamming logs even on close.
const int MAX_LOGS_TO_WRITE = filter.IsDebug() ? INT_MAX : 100;
@@ -106,18 +104,36 @@ private:
}
~Impl() {
running = false;
message_cv.notify_one();
Entry entry;
entry.final_entry = true;
message_queue.Push(entry);
backend_thread.join();
}
std::atomic_bool running{true};
std::mutex message_mutex, writing_mutex;
std::condition_variable message_cv;
Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr,
const char* function, std::string message) const {
using std::chrono::duration_cast;
using std::chrono::steady_clock;
Entry entry;
entry.timestamp =
duration_cast<std::chrono::microseconds>(steady_clock::now() - time_origin);
entry.log_class = log_class;
entry.log_level = log_level;
entry.filename = Common::TrimSourcePath(filename);
entry.line_num = line_nr;
entry.function = function;
entry.message = std::move(message);
return entry;
}
std::mutex writing_mutex;
std::thread backend_thread;
std::vector<std::unique_ptr<Backend>> backends;
Common::MPSCQueue<Log::Entry> message_queue;
Filter filter;
std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()};
};
void ConsoleBackend::Write(const Entry& entry) {
@@ -232,6 +248,7 @@ void DebuggerBackend::Write(const Entry& entry) {
CLS(Render) \
SUB(Render, Software) \
SUB(Render, OpenGL) \
SUB(Render, Vulkan) \
CLS(Audio) \
SUB(Audio, DSP) \
SUB(Audio, Sink) \
@@ -275,25 +292,6 @@ const char* GetLevelName(Level log_level) {
#undef LVL
}
Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr,
const char* function, std::string message) {
using std::chrono::duration_cast;
using std::chrono::steady_clock;
static steady_clock::time_point time_origin = steady_clock::now();
Entry entry;
entry.timestamp = duration_cast<std::chrono::microseconds>(steady_clock::now() - time_origin);
entry.log_class = log_class;
entry.log_level = log_level;
entry.filename = Common::TrimSourcePath(filename);
entry.line_num = line_nr;
entry.function = function;
entry.message = std::move(message);
return entry;
}
void SetGlobalFilter(const Filter& filter) {
Impl::Instance().SetGlobalFilter(filter);
}
@@ -318,9 +316,7 @@ void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
if (!filter.CheckMessage(log_class, log_level))
return;
Entry entry =
CreateEntry(log_class, log_level, filename, line_num, function, fmt::vformat(format, args));
instance.PushEntry(std::move(entry));
instance.PushEntry(log_class, log_level, filename, line_num, function,
fmt::vformat(format, args));
}
} // namespace Log

View File

@@ -27,6 +27,7 @@ struct Entry {
unsigned int line_num;
std::string function;
std::string message;
bool final_entry = false;
Entry() = default;
Entry(Entry&& o) = default;
@@ -134,10 +135,6 @@ const char* GetLogClassName(Class log_class);
*/
const char* GetLevelName(Level log_level);
/// Creates a log entry by formatting the given source location, and message.
Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr,
const char* function, std::string message);
/**
* The global filter will prevent any messages from even being processed if they are filtered. Each
* backend can have a filter, but if the level is lower than the global filter, the backend will

View File

@@ -112,6 +112,7 @@ enum class Class : ClassType {
Render, ///< Emulator video output and hardware acceleration
Render_Software, ///< Software renderer backend
Render_OpenGL, ///< OpenGL backend
Render_Vulkan, ///< Vulkan backend
Audio, ///< Audio emulation
Audio_DSP, ///< The HLE implementation of the DSP
Audio_Sink, ///< Emulator audio output backend

View File

@@ -7,7 +7,7 @@
#include <cstdlib>
#include <type_traits>
namespace MathUtil {
namespace Common {
constexpr float PI = 3.14159265f;
@@ -41,4 +41,4 @@ struct Rectangle {
}
};
} // namespace MathUtil
} // namespace Common

View File

@@ -6,12 +6,12 @@
#include "common/vector_math.h"
namespace Math {
namespace Common {
template <typename T>
class Quaternion {
public:
Math::Vec3<T> xyz;
Vec3<T> xyz;
T w{};
Quaternion<decltype(-T{})> Inverse() const {
@@ -38,12 +38,12 @@ public:
};
template <typename T>
auto QuaternionRotate(const Quaternion<T>& q, const Math::Vec3<T>& v) {
auto QuaternionRotate(const Quaternion<T>& q, const Vec3<T>& v) {
return v + 2 * Cross(q.xyz, Cross(q.xyz, v) + v * q.w);
}
inline Quaternion<float> MakeQuaternion(const Math::Vec3<float>& axis, float angle) {
inline Quaternion<float> MakeQuaternion(const Vec3<float>& axis, float angle) {
return {axis * std::sin(angle / 2), std::cos(angle / 2)};
}
} // namespace Math
} // namespace Common

View File

@@ -11,6 +11,7 @@
#define BUILD_DATE "@BUILD_DATE@"
#define BUILD_FULLNAME "@BUILD_FULLNAME@"
#define BUILD_VERSION "@BUILD_VERSION@"
#define SHADER_CACHE_VERSION "@SHADER_CACHE_VERSION@"
namespace Common {
@@ -21,6 +22,7 @@ const char g_build_name[] = BUILD_NAME;
const char g_build_date[] = BUILD_DATE;
const char g_build_fullname[] = BUILD_FULLNAME;
const char g_build_version[] = BUILD_VERSION;
const char g_shader_cache_version[] = SHADER_CACHE_VERSION;
} // namespace

View File

@@ -13,5 +13,6 @@ extern const char g_build_name[];
extern const char g_build_date[];
extern const char g_build_fullname[];
extern const char g_build_version[];
extern const char g_shader_cache_version[];
} // namespace Common

View File

@@ -28,8 +28,8 @@
#include <cstring>
#include "common/common_types.h"
// GCC 4.6+
#if __GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
// GCC
#ifdef __GNUC__
#if __BYTE_ORDER__ && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) && !defined(COMMON_LITTLE_ENDIAN)
#define COMMON_LITTLE_ENDIAN 1
@@ -38,7 +38,7 @@
#endif
// LLVM/clang
#elif __clang__
#elif defined(__clang__)
#if __LITTLE_ENDIAN__ && !defined(COMMON_LITTLE_ENDIAN)
#define COMMON_LITTLE_ENDIAN 1

View File

@@ -7,17 +7,17 @@
// a simple lockless thread-safe,
// single reader, single writer queue
#include <algorithm>
#include <atomic>
#include <condition_variable>
#include <cstddef>
#include <mutex>
#include "common/common_types.h"
#include <utility>
namespace Common {
template <typename T, bool NeedSize = true>
template <typename T>
class SPSCQueue {
public:
SPSCQueue() : size(0) {
SPSCQueue() {
write_ptr = read_ptr = new ElementPtr();
}
~SPSCQueue() {
@@ -25,13 +25,12 @@ public:
delete read_ptr;
}
u32 Size() const {
static_assert(NeedSize, "using Size() on FifoQueue without NeedSize");
std::size_t Size() const {
return size.load();
}
bool Empty() const {
return !read_ptr->next.load();
return Size() == 0;
}
T& Front() const {
@@ -47,13 +46,14 @@ public:
ElementPtr* new_ptr = new ElementPtr();
write_ptr->next.store(new_ptr, std::memory_order_release);
write_ptr = new_ptr;
if (NeedSize)
size++;
cv.notify_one();
++size;
}
void Pop() {
if (NeedSize)
size--;
--size;
ElementPtr* tmpptr = read_ptr;
// advance the read pointer
read_ptr = tmpptr->next.load();
@@ -66,8 +66,7 @@ public:
if (Empty())
return false;
if (NeedSize)
size--;
--size;
ElementPtr* tmpptr = read_ptr;
read_ptr = tmpptr->next.load(std::memory_order_acquire);
@@ -77,6 +76,16 @@ public:
return true;
}
T PopWait() {
if (Empty()) {
std::unique_lock<std::mutex> lock(cv_mutex);
cv.wait(lock, [this]() { return !Empty(); });
}
T t;
Pop(t);
return t;
}
// not thread-safe
void Clear() {
size.store(0);
@@ -89,7 +98,7 @@ private:
// and a pointer to the next ElementPtr
class ElementPtr {
public:
ElementPtr() : next(nullptr) {}
ElementPtr() {}
~ElementPtr() {
ElementPtr* next_ptr = next.load();
@@ -98,21 +107,23 @@ private:
}
T current;
std::atomic<ElementPtr*> next;
std::atomic<ElementPtr*> next{nullptr};
};
ElementPtr* write_ptr;
ElementPtr* read_ptr;
std::atomic<u32> size;
std::atomic_size_t size{0};
std::mutex cv_mutex;
std::condition_variable cv;
};
// a simple thread-safe,
// single reader, multiple writer queue
template <typename T, bool NeedSize = true>
template <typename T>
class MPSCQueue {
public:
u32 Size() const {
std::size_t Size() const {
return spsc_queue.Size();
}
@@ -138,13 +149,17 @@ public:
return spsc_queue.Pop(t);
}
T PopWait() {
return spsc_queue.PopWait();
}
// not thread-safe
void Clear() {
spsc_queue.Clear();
}
private:
SPSCQueue<T, NeedSize> spsc_queue;
SPSCQueue<T> spsc_queue;
std::mutex write_lock;
};
} // namespace Common

View File

@@ -33,7 +33,7 @@
#include <cmath>
#include <type_traits>
namespace Math {
namespace Common {
template <typename T>
class Vec2;
@@ -690,4 +690,4 @@ constexpr Vec4<T> MakeVec(const T& x, const Vec3<T>& yzw) {
return MakeVec(x, yzw[0], yzw[1], yzw[2]);
}
} // namespace Math
} // namespace Common

View File

@@ -88,11 +88,15 @@ add_library(core STATIC
frontend/applets/profile_select.h
frontend/applets/software_keyboard.cpp
frontend/applets/software_keyboard.h
frontend/applets/web_browser.cpp
frontend/applets/web_browser.h
frontend/emu_window.cpp
frontend/emu_window.h
frontend/framebuffer_layout.cpp
frontend/framebuffer_layout.h
frontend/input.h
frontend/scope_acquire_window_context.cpp
frontend/scope_acquire_window_context.h
gdbstub/gdbstub.cpp
gdbstub/gdbstub.h
hle/ipc.h
@@ -136,8 +140,6 @@ add_library(core STATIC
hle/kernel/svc_wrap.h
hle/kernel/thread.cpp
hle/kernel/thread.h
hle/kernel/timer.cpp
hle/kernel/timer.h
hle/kernel/vm_manager.cpp
hle/kernel/vm_manager.h
hle/kernel/wait_object.cpp
@@ -173,6 +175,8 @@ add_library(core STATIC
hle/service/am/applets/software_keyboard.h
hle/service/am/applets/stub_applet.cpp
hle/service/am/applets/stub_applet.h
hle/service/am/applets/web_browser.cpp
hle/service/am/applets/web_browser.h
hle/service/am/idle.cpp
hle/service/am/idle.h
hle/service/am/omm.cpp
@@ -213,6 +217,7 @@ add_library(core STATIC
hle/service/audio/audren_u.h
hle/service/audio/codecctl.cpp
hle/service/audio/codecctl.h
hle/service/audio/errors.h
hle/service/audio/hwopus.cpp
hle/service/audio/hwopus.h
hle/service/bcat/bcat.cpp
@@ -396,6 +401,10 @@ add_library(core STATIC
hle/service/time/time.h
hle/service/usb/usb.cpp
hle/service/usb/usb.h
hle/service/vi/display/vi_display.cpp
hle/service/vi/display/vi_display.h
hle/service/vi/layer/vi_layer.cpp
hle/service/vi/layer/vi_layer.h
hle/service/vi/vi.cpp
hle/service/vi/vi.h
hle/service/vi/vi_m.cpp

View File

@@ -112,14 +112,14 @@ public:
// Always execute at least one tick.
amortized_ticks = std::max<u64>(amortized_ticks, 1);
CoreTiming::AddTicks(amortized_ticks);
parent.core_timing.AddTicks(amortized_ticks);
num_interpreted_instructions = 0;
}
u64 GetTicksRemaining() override {
return std::max(CoreTiming::GetDowncount(), 0);
return std::max(parent.core_timing.GetDowncount(), 0);
}
u64 GetCNTPCT() override {
return CoreTiming::GetTicks();
return parent.core_timing.GetTicks();
}
ARM_Dynarmic& parent;
@@ -172,8 +172,10 @@ void ARM_Dynarmic::Step() {
cb->InterpreterFallback(jit->GetPC(), 1);
}
ARM_Dynarmic::ARM_Dynarmic(ExclusiveMonitor& exclusive_monitor, std::size_t core_index)
: cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), core_index{core_index},
ARM_Dynarmic::ARM_Dynarmic(Timing::CoreTiming& core_timing, ExclusiveMonitor& exclusive_monitor,
std::size_t core_index)
: cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), inner_unicorn{core_timing},
core_index{core_index}, core_timing{core_timing},
exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {
ThreadContext ctx{};
inner_unicorn.SaveContext(ctx);

View File

@@ -16,6 +16,10 @@ namespace Memory {
struct PageTable;
}
namespace Core::Timing {
class CoreTiming;
}
namespace Core {
class ARM_Dynarmic_Callbacks;
@@ -23,7 +27,8 @@ class DynarmicExclusiveMonitor;
class ARM_Dynarmic final : public ARM_Interface {
public:
ARM_Dynarmic(ExclusiveMonitor& exclusive_monitor, std::size_t core_index);
ARM_Dynarmic(Timing::CoreTiming& core_timing, ExclusiveMonitor& exclusive_monitor,
std::size_t core_index);
~ARM_Dynarmic();
void MapBackingMemory(VAddr address, std::size_t size, u8* memory,
@@ -62,6 +67,7 @@ private:
ARM_Unicorn inner_unicorn;
std::size_t core_index;
Timing::CoreTiming& core_timing;
DynarmicExclusiveMonitor& exclusive_monitor;
Memory::PageTable* current_page_table = nullptr;

View File

@@ -72,7 +72,7 @@ static bool UnmappedMemoryHook(uc_engine* uc, uc_mem_type type, u64 addr, int si
return {};
}
ARM_Unicorn::ARM_Unicorn() {
ARM_Unicorn::ARM_Unicorn(Timing::CoreTiming& core_timing) : core_timing{core_timing} {
CHECKED(uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc));
auto fpv = 3 << 20;
@@ -177,7 +177,7 @@ void ARM_Unicorn::Run() {
if (GDBStub::IsServerEnabled()) {
ExecuteInstructions(std::max(4000000, 0));
} else {
ExecuteInstructions(std::max(CoreTiming::GetDowncount(), 0));
ExecuteInstructions(std::max(core_timing.GetDowncount(), 0));
}
}
@@ -190,7 +190,7 @@ MICROPROFILE_DEFINE(ARM_Jit_Unicorn, "ARM JIT", "Unicorn", MP_RGB(255, 64, 64));
void ARM_Unicorn::ExecuteInstructions(int num_instructions) {
MICROPROFILE_SCOPE(ARM_Jit_Unicorn);
CHECKED(uc_emu_start(uc, GetPC(), 1ULL << 63, 0, num_instructions));
CoreTiming::AddTicks(num_instructions);
core_timing.AddTicks(num_instructions);
if (GDBStub::IsServerEnabled()) {
if (last_bkpt_hit) {
uc_reg_write(uc, UC_ARM64_REG_PC, &last_bkpt.address);

View File

@@ -9,12 +9,17 @@
#include "core/arm/arm_interface.h"
#include "core/gdbstub/gdbstub.h"
namespace Core::Timing {
class CoreTiming;
}
namespace Core {
class ARM_Unicorn final : public ARM_Interface {
public:
ARM_Unicorn();
explicit ARM_Unicorn(Timing::CoreTiming& core_timing);
~ARM_Unicorn();
void MapBackingMemory(VAddr address, std::size_t size, u8* memory,
Kernel::VMAPermission perms) override;
void UnmapMemory(VAddr address, std::size_t size) override;
@@ -43,6 +48,7 @@ public:
private:
uc_engine* uc{};
Timing::CoreTiming& core_timing;
GDBStub::BreakpointAddress last_bkpt{};
bool last_bkpt_hit;
};

View File

@@ -30,10 +30,14 @@
#include "core/hle/service/sm/sm.h"
#include "core/loader/loader.h"
#include "core/perf_stats.h"
#include "core/settings.h"
#include "core/telemetry_session.h"
#include "frontend/applets/profile_select.h"
#include "frontend/applets/software_keyboard.h"
#include "frontend/applets/web_browser.h"
#include "video_core/debug_utils/debug_utils.h"
#include "video_core/gpu.h"
#include "video_core/gpu_asynch.h"
#include "video_core/gpu_synch.h"
#include "video_core/renderer_base.h"
#include "video_core/video_core.h"
@@ -75,6 +79,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
return vfs->OpenFile(path, FileSys::Mode::Read);
}
struct System::Impl {
explicit Impl(System& system) : kernel{system} {}
Cpu& CurrentCpuCore() {
return cpu_core_manager.GetCurrentCore();
@@ -91,9 +96,14 @@ struct System::Impl {
ResultStatus Init(System& system, Frontend::EmuWindow& emu_window) {
LOG_DEBUG(HW_Memory, "initialized OK");
CoreTiming::Init();
core_timing.Initialize();
kernel.Initialize();
const auto current_time = std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch());
Settings::values.custom_rtc_differential =
Settings::values.custom_rtc.value_or(current_time) - current_time;
// Create a default fs if one doesn't already exist.
if (virtual_filesystem == nullptr)
virtual_filesystem = std::make_shared<FileSys::RealVfsFilesystem>();
@@ -103,6 +113,8 @@ struct System::Impl {
profile_selector = std::make_unique<Core::Frontend::DefaultProfileSelectApplet>();
if (software_keyboard == nullptr)
software_keyboard = std::make_unique<Core::Frontend::DefaultSoftwareKeyboardApplet>();
if (web_browser == nullptr)
web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>();
auto main_process = Kernel::Process::Create(kernel, "main");
kernel.MakeCurrentProcess(main_process.get());
@@ -110,18 +122,24 @@ struct System::Impl {
telemetry_session = std::make_unique<Core::TelemetrySession>();
service_manager = std::make_shared<Service::SM::ServiceManager>();
Service::Init(service_manager, *virtual_filesystem);
Service::Init(service_manager, system, *virtual_filesystem);
GDBStub::Init();
renderer = VideoCore::CreateRenderer(emu_window);
renderer = VideoCore::CreateRenderer(emu_window, system);
if (!renderer->Init()) {
return ResultStatus::ErrorVideoCore;
}
gpu_core = std::make_unique<Tegra::GPU>(renderer->Rasterizer());
is_powered_on = true;
if (Settings::values.use_asynchronous_gpu_emulation) {
gpu_core = std::make_unique<VideoCommon::GPUAsynch>(system, *renderer);
} else {
gpu_core = std::make_unique<VideoCommon::GPUSynch>(system, *renderer);
}
cpu_core_manager.Initialize(system);
is_powered_on = true;
LOG_DEBUG(Core, "Initialized OK");
// Reset counters and set time origin to current frame
@@ -165,19 +183,20 @@ struct System::Impl {
return static_cast<ResultStatus>(static_cast<u32>(ResultStatus::ErrorLoader) +
static_cast<u32>(load_result));
}
status = ResultStatus::Success;
return status;
}
void Shutdown() {
// Log last frame performance stats
auto perf_results = GetAndResetPerfStats();
Telemetry().AddField(Telemetry::FieldType::Performance, "Shutdown_EmulationSpeed",
perf_results.emulation_speed * 100.0);
Telemetry().AddField(Telemetry::FieldType::Performance, "Shutdown_Framerate",
perf_results.game_fps);
Telemetry().AddField(Telemetry::FieldType::Performance, "Shutdown_Frametime",
perf_results.frametime * 1000.0);
const auto perf_results = GetAndResetPerfStats();
telemetry_session->AddField(Telemetry::FieldType::Performance, "Shutdown_EmulationSpeed",
perf_results.emulation_speed * 100.0);
telemetry_session->AddField(Telemetry::FieldType::Performance, "Shutdown_Framerate",
perf_results.game_fps);
telemetry_session->AddField(Telemetry::FieldType::Performance, "Shutdown_Frametime",
perf_results.frametime * 1000.0);
is_powered_on = false;
@@ -194,11 +213,16 @@ struct System::Impl {
// Shutdown kernel and core timing
kernel.Shutdown();
CoreTiming::Shutdown();
core_timing.Shutdown();
// Close app loader
app_loader.reset();
// Clear all applets
profile_selector.reset();
software_keyboard.reset();
web_browser.reset();
LOG_DEBUG(Core, "Shutdown OK");
}
@@ -216,9 +240,10 @@ struct System::Impl {
}
PerfStatsResults GetAndResetPerfStats() {
return perf_stats.GetAndResetStats(CoreTiming::GetGlobalTimeUs());
return perf_stats.GetAndResetStats(core_timing.GetGlobalTimeUs());
}
Timing::CoreTiming core_timing;
Kernel::KernelCore kernel;
/// RealVfsFilesystem instance
FileSys::VirtualFilesystem virtual_filesystem;
@@ -233,6 +258,7 @@ struct System::Impl {
/// Frontend applets
std::unique_ptr<Core::Frontend::ProfileSelectApplet> profile_selector;
std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet> software_keyboard;
std::unique_ptr<Core::Frontend::WebBrowserApplet> web_browser;
/// Service manager
std::shared_ptr<Service::SM::ServiceManager> service_manager;
@@ -247,7 +273,7 @@ struct System::Impl {
Core::FrameLimiter frame_limiter;
};
System::System() : impl{std::make_unique<Impl>()} {}
System::System() : impl{std::make_unique<Impl>(*this)} {}
System::~System() = default;
Cpu& System::CurrentCpuCore() {
@@ -379,6 +405,14 @@ const Kernel::KernelCore& System::Kernel() const {
return impl->kernel;
}
Timing::CoreTiming& System::CoreTiming() {
return impl->core_timing;
}
const Timing::CoreTiming& System::CoreTiming() const {
return impl->core_timing;
}
Core::PerfStats& System::GetPerfStats() {
return impl->perf_stats;
}
@@ -427,22 +461,34 @@ std::shared_ptr<FileSys::VfsFilesystem> System::GetFilesystem() const {
return impl->virtual_filesystem;
}
void System::SetProfileSelector(std::unique_ptr<Core::Frontend::ProfileSelectApplet> applet) {
void System::SetProfileSelector(std::unique_ptr<Frontend::ProfileSelectApplet> applet) {
impl->profile_selector = std::move(applet);
}
const Core::Frontend::ProfileSelectApplet& System::GetProfileSelector() const {
const Frontend::ProfileSelectApplet& System::GetProfileSelector() const {
return *impl->profile_selector;
}
void System::SetSoftwareKeyboard(std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet> applet) {
void System::SetSoftwareKeyboard(std::unique_ptr<Frontend::SoftwareKeyboardApplet> applet) {
impl->software_keyboard = std::move(applet);
}
const Core::Frontend::SoftwareKeyboardApplet& System::GetSoftwareKeyboard() const {
const Frontend::SoftwareKeyboardApplet& System::GetSoftwareKeyboard() const {
return *impl->software_keyboard;
}
void System::SetWebBrowser(std::unique_ptr<Frontend::WebBrowserApplet> applet) {
impl->web_browser = std::move(applet);
}
Frontend::WebBrowserApplet& System::GetWebBrowser() {
return *impl->web_browser;
}
const Frontend::WebBrowserApplet& System::GetWebBrowser() const {
return *impl->web_browser;
}
System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) {
return impl->Init(*this, emu_window);
}

View File

@@ -11,11 +11,12 @@
#include "common/common_types.h"
#include "core/file_sys/vfs_types.h"
#include "core/hle/kernel/object.h"
#include "frontend/applets/profile_select.h"
namespace Core::Frontend {
class EmuWindow;
class ProfileSelectApplet;
class SoftwareKeyboardApplet;
class WebBrowserApplet;
} // namespace Core::Frontend
namespace FileSys {
@@ -46,6 +47,10 @@ namespace VideoCore {
class RendererBase;
} // namespace VideoCore
namespace Core::Timing {
class CoreTiming;
}
namespace Core {
class ARM_Interface;
@@ -204,6 +209,12 @@ public:
/// Provides a constant pointer to the current process.
const Kernel::Process* CurrentProcess() const;
/// Provides a reference to the core timing instance.
Timing::CoreTiming& CoreTiming();
/// Provides a constant reference to the core timing instance.
const Timing::CoreTiming& CoreTiming() const;
/// Provides a reference to the kernel instance.
Kernel::KernelCore& Kernel();
@@ -242,13 +253,18 @@ public:
std::shared_ptr<FileSys::VfsFilesystem> GetFilesystem() const;
void SetProfileSelector(std::unique_ptr<Core::Frontend::ProfileSelectApplet> applet);
void SetProfileSelector(std::unique_ptr<Frontend::ProfileSelectApplet> applet);
const Core::Frontend::ProfileSelectApplet& GetProfileSelector() const;
const Frontend::ProfileSelectApplet& GetProfileSelector() const;
void SetSoftwareKeyboard(std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet> applet);
void SetSoftwareKeyboard(std::unique_ptr<Frontend::SoftwareKeyboardApplet> applet);
const Core::Frontend::SoftwareKeyboardApplet& GetSoftwareKeyboard() const;
const Frontend::SoftwareKeyboardApplet& GetSoftwareKeyboard() const;
void SetWebBrowser(std::unique_ptr<Frontend::WebBrowserApplet> applet);
Frontend::WebBrowserApplet& GetWebBrowser();
const Frontend::WebBrowserApplet& GetWebBrowser() const;
private:
System();
@@ -277,10 +293,6 @@ inline ARM_Interface& CurrentArmInterface() {
return System::GetInstance().CurrentArmInterface();
}
inline TelemetrySession& Telemetry() {
return System::GetInstance().TelemetrySession();
}
inline Kernel::Process* CurrentProcess() {
return System::GetInstance().CurrentProcess();
}

View File

@@ -11,6 +11,7 @@
#endif
#include "core/arm/exclusive_monitor.h"
#include "core/arm/unicorn/arm_unicorn.h"
#include "core/core.h"
#include "core/core_cpu.h"
#include "core/core_timing.h"
#include "core/hle/kernel/scheduler.h"
@@ -49,20 +50,21 @@ bool CpuBarrier::Rendezvous() {
return false;
}
Cpu::Cpu(ExclusiveMonitor& exclusive_monitor, CpuBarrier& cpu_barrier, std::size_t core_index)
: cpu_barrier{cpu_barrier}, core_index{core_index} {
Cpu::Cpu(System& system, ExclusiveMonitor& exclusive_monitor, CpuBarrier& cpu_barrier,
std::size_t core_index)
: cpu_barrier{cpu_barrier}, core_timing{system.CoreTiming()}, core_index{core_index} {
if (Settings::values.use_cpu_jit) {
#ifdef ARCHITECTURE_x86_64
arm_interface = std::make_unique<ARM_Dynarmic>(exclusive_monitor, core_index);
arm_interface = std::make_unique<ARM_Dynarmic>(core_timing, exclusive_monitor, core_index);
#else
arm_interface = std::make_unique<ARM_Unicorn>();
LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available");
#endif
} else {
arm_interface = std::make_unique<ARM_Unicorn>();
arm_interface = std::make_unique<ARM_Unicorn>(core_timing);
}
scheduler = std::make_unique<Kernel::Scheduler>(*arm_interface);
scheduler = std::make_unique<Kernel::Scheduler>(system, *arm_interface);
}
Cpu::~Cpu() = default;
@@ -93,14 +95,14 @@ void Cpu::RunLoop(bool tight_loop) {
if (IsMainCore()) {
// TODO(Subv): Only let CoreTiming idle if all 4 cores are idling.
CoreTiming::Idle();
CoreTiming::Advance();
core_timing.Idle();
core_timing.Advance();
}
PrepareReschedule();
} else {
if (IsMainCore()) {
CoreTiming::Advance();
core_timing.Advance();
}
if (tight_loop) {

View File

@@ -15,6 +15,14 @@ namespace Kernel {
class Scheduler;
}
namespace Core {
class System;
}
namespace Core::Timing {
class CoreTiming;
}
namespace Core {
class ARM_Interface;
@@ -41,7 +49,8 @@ private:
class Cpu {
public:
Cpu(ExclusiveMonitor& exclusive_monitor, CpuBarrier& cpu_barrier, std::size_t core_index);
Cpu(System& system, ExclusiveMonitor& exclusive_monitor, CpuBarrier& cpu_barrier,
std::size_t core_index);
~Cpu();
void RunLoop(bool tight_loop = true);
@@ -82,6 +91,7 @@ private:
std::unique_ptr<ARM_Interface> arm_interface;
CpuBarrier& cpu_barrier;
std::unique_ptr<Kernel::Scheduler> scheduler;
Timing::CoreTiming& core_timing;
std::atomic<bool> reschedule_pending = false;
std::size_t core_index;

View File

@@ -8,71 +8,60 @@
#include <mutex>
#include <string>
#include <tuple>
#include <unordered_map>
#include <vector>
#include "common/assert.h"
#include "common/thread.h"
#include "common/threadsafe_queue.h"
#include "core/core_timing_util.h"
namespace CoreTiming {
namespace Core::Timing {
static s64 global_timer;
static int slice_length;
static int downcount;
constexpr int MAX_SLICE_LENGTH = 20000;
struct EventType {
TimedCallback callback;
const std::string* name;
};
struct Event {
struct CoreTiming::Event {
s64 time;
u64 fifo_order;
u64 userdata;
const EventType* type;
// Sort by time, unless the times are the same, in which case sort by
// the order added to the queue
friend bool operator>(const Event& left, const Event& right) {
return std::tie(left.time, left.fifo_order) > std::tie(right.time, right.fifo_order);
}
friend bool operator<(const Event& left, const Event& right) {
return std::tie(left.time, left.fifo_order) < std::tie(right.time, right.fifo_order);
}
};
// Sort by time, unless the times are the same, in which case sort by the order added to the queue
static bool operator>(const Event& left, const Event& right) {
return std::tie(left.time, left.fifo_order) > std::tie(right.time, right.fifo_order);
CoreTiming::CoreTiming() = default;
CoreTiming::~CoreTiming() = default;
void CoreTiming::Initialize() {
downcount = MAX_SLICE_LENGTH;
slice_length = MAX_SLICE_LENGTH;
global_timer = 0;
idled_cycles = 0;
// The time between CoreTiming being initialized and the first call to Advance() is considered
// the slice boundary between slice -1 and slice 0. Dispatcher loops must call Advance() before
// executing the first cycle of each slice to prepare the slice length and downcount for
// that slice.
is_global_timer_sane = true;
event_fifo_id = 0;
const auto empty_timed_callback = [](u64, s64) {};
ev_lost = RegisterEvent("_lost_event", empty_timed_callback);
}
static bool operator<(const Event& left, const Event& right) {
return std::tie(left.time, left.fifo_order) < std::tie(right.time, right.fifo_order);
void CoreTiming::Shutdown() {
MoveEvents();
ClearPendingEvents();
UnregisterAllEvents();
}
// unordered_map stores each element separately as a linked list node so pointers to elements
// remain stable regardless of rehashes/resizing.
static std::unordered_map<std::string, EventType> event_types;
// The queue is a min-heap using std::make_heap/push_heap/pop_heap.
// We don't use std::priority_queue because we need to be able to serialize, unserialize and
// erase arbitrary events (RemoveEvent()) regardless of the queue order. These aren't accomodated
// by the standard adaptor class.
static std::vector<Event> event_queue;
static u64 event_fifo_id;
// the queue for storing the events from other threads threadsafe until they will be added
// to the event_queue by the emu thread
static Common::MPSCQueue<Event, false> ts_queue;
// the queue for unscheduling the events from other threads threadsafe
static Common::MPSCQueue<std::pair<const EventType*, u64>, false> unschedule_queue;
constexpr int MAX_SLICE_LENGTH = 20000;
static s64 idled_cycles;
// Are we in a function that has been called from Advance()
// If events are sheduled from a function that gets called from Advance(),
// don't change slice_length and downcount.
static bool is_global_timer_sane;
static EventType* ev_lost = nullptr;
static void EmptyTimedCallback(u64 userdata, s64 cyclesLate) {}
EventType* RegisterEvent(const std::string& name, TimedCallback callback) {
EventType* CoreTiming::RegisterEvent(const std::string& name, TimedCallback callback) {
// check for existing type with same name.
// we want event type names to remain unique so that we can use them for serialization.
ASSERT_MSG(event_types.find(name) == event_types.end(),
@@ -86,71 +75,31 @@ EventType* RegisterEvent(const std::string& name, TimedCallback callback) {
return event_type;
}
void UnregisterAllEvents() {
void CoreTiming::UnregisterAllEvents() {
ASSERT_MSG(event_queue.empty(), "Cannot unregister events with events pending");
event_types.clear();
}
void Init() {
downcount = MAX_SLICE_LENGTH;
slice_length = MAX_SLICE_LENGTH;
global_timer = 0;
idled_cycles = 0;
// The time between CoreTiming being intialized and the first call to Advance() is considered
// the slice boundary between slice -1 and slice 0. Dispatcher loops must call Advance() before
// executing the first cycle of each slice to prepare the slice length and downcount for
// that slice.
is_global_timer_sane = true;
event_fifo_id = 0;
ev_lost = RegisterEvent("_lost_event", &EmptyTimedCallback);
}
void Shutdown() {
MoveEvents();
ClearPendingEvents();
UnregisterAllEvents();
}
// This should only be called from the CPU thread. If you are calling
// it from any other thread, you are doing something evil
u64 GetTicks() {
u64 ticks = static_cast<u64>(global_timer);
if (!is_global_timer_sane) {
ticks += slice_length - downcount;
}
return ticks;
}
void AddTicks(u64 ticks) {
downcount -= static_cast<int>(ticks);
}
u64 GetIdleTicks() {
return static_cast<u64>(idled_cycles);
}
void ClearPendingEvents() {
event_queue.clear();
}
void ScheduleEvent(s64 cycles_into_future, const EventType* event_type, u64 userdata) {
void CoreTiming::ScheduleEvent(s64 cycles_into_future, const EventType* event_type, u64 userdata) {
ASSERT(event_type != nullptr);
s64 timeout = GetTicks() + cycles_into_future;
const s64 timeout = GetTicks() + cycles_into_future;
// If this event needs to be scheduled before the next advance(), force one early
if (!is_global_timer_sane)
if (!is_global_timer_sane) {
ForceExceptionCheck(cycles_into_future);
}
event_queue.emplace_back(Event{timeout, event_fifo_id++, userdata, event_type});
std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>());
}
void ScheduleEventThreadsafe(s64 cycles_into_future, const EventType* event_type, u64 userdata) {
void CoreTiming::ScheduleEventThreadsafe(s64 cycles_into_future, const EventType* event_type,
u64 userdata) {
ts_queue.Push(Event{global_timer + cycles_into_future, 0, userdata, event_type});
}
void UnscheduleEvent(const EventType* event_type, u64 userdata) {
auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) {
void CoreTiming::UnscheduleEvent(const EventType* event_type, u64 userdata) {
const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) {
return e.type == event_type && e.userdata == userdata;
});
@@ -161,13 +110,33 @@ void UnscheduleEvent(const EventType* event_type, u64 userdata) {
}
}
void UnscheduleEventThreadsafe(const EventType* event_type, u64 userdata) {
void CoreTiming::UnscheduleEventThreadsafe(const EventType* event_type, u64 userdata) {
unschedule_queue.Push(std::make_pair(event_type, userdata));
}
void RemoveEvent(const EventType* event_type) {
auto itr = std::remove_if(event_queue.begin(), event_queue.end(),
[&](const Event& e) { return e.type == event_type; });
u64 CoreTiming::GetTicks() const {
u64 ticks = static_cast<u64>(global_timer);
if (!is_global_timer_sane) {
ticks += slice_length - downcount;
}
return ticks;
}
u64 CoreTiming::GetIdleTicks() const {
return static_cast<u64>(idled_cycles);
}
void CoreTiming::AddTicks(u64 ticks) {
downcount -= static_cast<int>(ticks);
}
void CoreTiming::ClearPendingEvents() {
event_queue.clear();
}
void CoreTiming::RemoveEvent(const EventType* event_type) {
const auto itr = std::remove_if(event_queue.begin(), event_queue.end(),
[&](const Event& e) { return e.type == event_type; });
// Removing random items breaks the invariant so we have to re-establish it.
if (itr != event_queue.end()) {
@@ -176,22 +145,24 @@ void RemoveEvent(const EventType* event_type) {
}
}
void RemoveNormalAndThreadsafeEvent(const EventType* event_type) {
void CoreTiming::RemoveNormalAndThreadsafeEvent(const EventType* event_type) {
MoveEvents();
RemoveEvent(event_type);
}
void ForceExceptionCheck(s64 cycles) {
void CoreTiming::ForceExceptionCheck(s64 cycles) {
cycles = std::max<s64>(0, cycles);
if (downcount > cycles) {
// downcount is always (much) smaller than MAX_INT so we can safely cast cycles to an int
// here. Account for cycles already executed by adjusting the g.slice_length
slice_length -= downcount - static_cast<int>(cycles);
downcount = static_cast<int>(cycles);
if (downcount <= cycles) {
return;
}
// downcount is always (much) smaller than MAX_INT so we can safely cast cycles to an int
// here. Account for cycles already executed by adjusting the g.slice_length
slice_length -= downcount - static_cast<int>(cycles);
downcount = static_cast<int>(cycles);
}
void MoveEvents() {
void CoreTiming::MoveEvents() {
for (Event ev; ts_queue.Pop(ev);) {
ev.fifo_order = event_fifo_id++;
event_queue.emplace_back(std::move(ev));
@@ -199,13 +170,13 @@ void MoveEvents() {
}
}
void Advance() {
void CoreTiming::Advance() {
MoveEvents();
for (std::pair<const EventType*, u64> ev; unschedule_queue.Pop(ev);) {
UnscheduleEvent(ev.first, ev.second);
}
int cycles_executed = slice_length - downcount;
const int cycles_executed = slice_length - downcount;
global_timer += cycles_executed;
slice_length = MAX_SLICE_LENGTH;
@@ -229,17 +200,17 @@ void Advance() {
downcount = slice_length;
}
void Idle() {
void CoreTiming::Idle() {
idled_cycles += downcount;
downcount = 0;
}
std::chrono::microseconds GetGlobalTimeUs() {
std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const {
return std::chrono::microseconds{GetTicks() * 1000000 / BASE_CLOCK_RATE};
}
int GetDowncount() {
int CoreTiming::GetDowncount() const {
return downcount;
}
} // namespace CoreTiming
} // namespace Core::Timing

View File

@@ -4,6 +4,27 @@
#pragma once
#include <chrono>
#include <functional>
#include <string>
#include <unordered_map>
#include <vector>
#include "common/common_types.h"
#include "common/threadsafe_queue.h"
namespace Core::Timing {
/// A callback that may be scheduled for a particular core timing event.
using TimedCallback = std::function<void(u64 userdata, int cycles_late)>;
/// Contains the characteristics of a particular event.
struct EventType {
/// The event's callback function.
TimedCallback callback;
/// A pointer to the name of the event.
const std::string* name;
};
/**
* This is a system to schedule events into the emulated machine's future. Time is measured
* in main CPU clock cycles.
@@ -16,80 +37,120 @@
* inside callback:
* ScheduleEvent(periodInCycles - cyclesLate, callback, "whatever")
*/
class CoreTiming {
public:
CoreTiming();
~CoreTiming();
#include <chrono>
#include <functional>
#include <string>
#include "common/common_types.h"
CoreTiming(const CoreTiming&) = delete;
CoreTiming(CoreTiming&&) = delete;
namespace CoreTiming {
CoreTiming& operator=(const CoreTiming&) = delete;
CoreTiming& operator=(CoreTiming&&) = delete;
struct EventType;
/// CoreTiming begins at the boundary of timing slice -1. An initial call to Advance() is
/// required to end slice - 1 and start slice 0 before the first cycle of code is executed.
void Initialize();
using TimedCallback = std::function<void(u64 userdata, int cycles_late)>;
/// Tears down all timing related functionality.
void Shutdown();
/**
* CoreTiming begins at the boundary of timing slice -1. An initial call to Advance() is
* required to end slice -1 and start slice 0 before the first cycle of code is executed.
*/
void Init();
void Shutdown();
/// Registers a core timing event with the given name and callback.
///
/// @param name The name of the core timing event to register.
/// @param callback The callback to execute for the event.
///
/// @returns An EventType instance representing the registered event.
///
/// @pre The name of the event being registered must be unique among all
/// registered events.
///
EventType* RegisterEvent(const std::string& name, TimedCallback callback);
/**
* This should only be called from the emu thread, if you are calling it any other thread, you are
* doing something evil
*/
u64 GetTicks();
u64 GetIdleTicks();
void AddTicks(u64 ticks);
/// Unregisters all registered events thus far.
void UnregisterAllEvents();
/**
* Returns the event_type identifier. if name is not unique, it will assert.
*/
EventType* RegisterEvent(const std::string& name, TimedCallback callback);
void UnregisterAllEvents();
/// After the first Advance, the slice lengths and the downcount will be reduced whenever an
/// event is scheduled earlier than the current values.
///
/// Scheduling from a callback will not update the downcount until the Advance() completes.
void ScheduleEvent(s64 cycles_into_future, const EventType* event_type, u64 userdata = 0);
/**
* After the first Advance, the slice lengths and the downcount will be reduced whenever an event
* is scheduled earlier than the current values.
* Scheduling from a callback will not update the downcount until the Advance() completes.
*/
void ScheduleEvent(s64 cycles_into_future, const EventType* event_type, u64 userdata = 0);
/// This is to be called when outside of hle threads, such as the graphics thread, wants to
/// schedule things to be executed on the main thread.
///
/// @note This doesn't change slice_length and thus events scheduled by this might be
/// called with a delay of up to MAX_SLICE_LENGTH
void ScheduleEventThreadsafe(s64 cycles_into_future, const EventType* event_type,
u64 userdata = 0);
/**
* This is to be called when outside of hle threads, such as the graphics thread, wants to
* schedule things to be executed on the main thread.
* Not that this doesn't change slice_length and thus events scheduled by this might be called
* with a delay of up to MAX_SLICE_LENGTH
*/
void ScheduleEventThreadsafe(s64 cycles_into_future, const EventType* event_type, u64 userdata);
void UnscheduleEvent(const EventType* event_type, u64 userdata);
void UnscheduleEventThreadsafe(const EventType* event_type, u64 userdata);
void UnscheduleEvent(const EventType* event_type, u64 userdata);
void UnscheduleEventThreadsafe(const EventType* event_type, u64 userdata);
/// We only permit one event of each type in the queue at a time.
void RemoveEvent(const EventType* event_type);
void RemoveNormalAndThreadsafeEvent(const EventType* event_type);
/// We only permit one event of each type in the queue at a time.
void RemoveEvent(const EventType* event_type);
void RemoveNormalAndThreadsafeEvent(const EventType* event_type);
void ForceExceptionCheck(s64 cycles);
/** Advance must be called at the beginning of dispatcher loops, not the end. Advance() ends
* the previous timing slice and begins the next one, you must Advance from the previous
* slice to the current one before executing any cycles. CoreTiming starts in slice -1 so an
* Advance() is required to initialize the slice length before the first cycle of emulated
* instructions is executed.
*/
void Advance();
void MoveEvents();
/// This should only be called from the emu thread, if you are calling it any other thread,
/// you are doing something evil
u64 GetTicks() const;
/// Pretend that the main CPU has executed enough cycles to reach the next event.
void Idle();
u64 GetIdleTicks() const;
/// Clear all pending events. This should ONLY be done on exit.
void ClearPendingEvents();
void AddTicks(u64 ticks);
void ForceExceptionCheck(s64 cycles);
/// Advance must be called at the beginning of dispatcher loops, not the end. Advance() ends
/// the previous timing slice and begins the next one, you must Advance from the previous
/// slice to the current one before executing any cycles. CoreTiming starts in slice -1 so an
/// Advance() is required to initialize the slice length before the first cycle of emulated
/// instructions is executed.
void Advance();
std::chrono::microseconds GetGlobalTimeUs();
/// Pretend that the main CPU has executed enough cycles to reach the next event.
void Idle();
int GetDowncount();
std::chrono::microseconds GetGlobalTimeUs() const;
} // namespace CoreTiming
int GetDowncount() const;
private:
struct Event;
/// Clear all pending events. This should ONLY be done on exit.
void ClearPendingEvents();
void MoveEvents();
s64 global_timer = 0;
s64 idled_cycles = 0;
int slice_length = 0;
int downcount = 0;
// Are we in a function that has been called from Advance()
// If events are scheduled from a function that gets called from Advance(),
// don't change slice_length and downcount.
bool is_global_timer_sane = false;
// The queue is a min-heap using std::make_heap/push_heap/pop_heap.
// We don't use std::priority_queue because we need to be able to serialize, unserialize and
// erase arbitrary events (RemoveEvent()) regardless of the queue order. These aren't
// accomodated by the standard adaptor class.
std::vector<Event> event_queue;
u64 event_fifo_id = 0;
// Stores each element separately as a linked list node so pointers to elements
// remain stable regardless of rehashes/resizing.
std::unordered_map<std::string, EventType> event_types;
// The queue for storing the events from other threads threadsafe until they will be added
// to the event_queue by the emu thread
Common::MPSCQueue<Event> ts_queue;
// The queue for unscheduling the events from other threads threadsafe
Common::MPSCQueue<std::pair<const EventType*, u64>> unschedule_queue;
EventType* ev_lost = nullptr;
};
} // namespace Core::Timing

View File

@@ -8,7 +8,7 @@
#include <limits>
#include "common/logging/log.h"
namespace CoreTiming {
namespace Core::Timing {
constexpr u64 MAX_VALUE_TO_MULTIPLY = std::numeric_limits<s64>::max() / BASE_CLOCK_RATE;
@@ -60,4 +60,4 @@ s64 nsToCycles(u64 ns) {
return (BASE_CLOCK_RATE * static_cast<s64>(ns)) / 1000000000;
}
} // namespace CoreTiming
} // namespace Core::Timing

View File

@@ -6,7 +6,7 @@
#include "common/common_types.h"
namespace CoreTiming {
namespace Core::Timing {
// The below clock rate is based on Switch's clockspeed being widely known as 1.020GHz
// The exact value used is of course unverified.
@@ -61,4 +61,4 @@ inline u64 cyclesToMs(s64 cycles) {
return cycles * 1000 / BASE_CLOCK_RATE;
}
} // namespace CoreTiming
} // namespace Core::Timing

View File

@@ -27,7 +27,7 @@ void CpuCoreManager::Initialize(System& system) {
exclusive_monitor = Cpu::MakeExclusiveMonitor(cores.size());
for (std::size_t index = 0; index < cores.size(); ++index) {
cores[index] = std::make_unique<Cpu>(*exclusive_monitor, *barrier, index);
cores[index] = std::make_unique<Cpu>(system, *exclusive_monitor, *barrier, index);
}
// Create threads for CPU cores 1-3, and build thread_to_cpu map

View File

@@ -398,7 +398,8 @@ static bool ValidCryptoRevisionString(std::string_view base, size_t begin, size_
}
void KeyManager::LoadFromFile(const std::string& filename, bool is_title_keys) {
std::ifstream file(filename);
std::ifstream file;
OpenFStream(file, filename, std::ios_base::in);
if (!file.is_open())
return;

View File

@@ -359,6 +359,8 @@ bool NCA::ReadPFS0Section(const NCASectionHeader& section, const NCASectionTable
dirs.push_back(std::move(npfs));
if (IsDirectoryExeFS(dirs.back()))
exefs = dirs.back();
else if (IsDirectoryLogoPartition(dirs.back()))
logo = dirs.back();
} else {
if (has_rights_id)
status = Loader::ResultStatus::ErrorIncorrectTitlekeyOrTitlekek;
@@ -546,4 +548,8 @@ u64 NCA::GetBaseIVFCOffset() const {
return ivfc_offset;
}
VirtualDir NCA::GetLogoPartition() const {
return logo;
}
} // namespace FileSys

View File

@@ -74,6 +74,13 @@ inline bool IsDirectoryExeFS(const std::shared_ptr<VfsDirectory>& pfs) {
return pfs->GetFile("main") != nullptr && pfs->GetFile("main.npdm") != nullptr;
}
inline bool IsDirectoryLogoPartition(const VirtualDir& pfs) {
// NintendoLogo is the static image in the top left corner while StartupMovie is the animation
// in the bottom right corner.
return pfs->GetFile("NintendoLogo.png") != nullptr &&
pfs->GetFile("StartupMovie.gif") != nullptr;
}
// An implementation of VfsDirectory that represents a Nintendo Content Archive (NCA) conatiner.
// After construction, use GetStatus to determine if the file is valid and ready to be used.
class NCA : public ReadOnlyVfsDirectory {
@@ -102,6 +109,8 @@ public:
// Returns the base ivfc offset used in BKTR patching.
u64 GetBaseIVFCOffset() const;
VirtualDir GetLogoPartition() const;
private:
bool CheckSupportedNCA(const NCAHeader& header);
bool HandlePotentialHeaderDecryption();
@@ -122,6 +131,7 @@ private:
VirtualFile romfs = nullptr;
VirtualDir exefs = nullptr;
VirtualDir logo = nullptr;
VirtualFile file;
VirtualFile bktr_base_romfs;
u64 ivfc_offset = 0;

View File

@@ -39,27 +39,4 @@ static_assert(sizeof(Entry) == 0x310, "Directory Entry struct isn't exactly 0x31
static_assert(offsetof(Entry, type) == 0x304, "Wrong offset for type in Entry.");
static_assert(offsetof(Entry, file_size) == 0x308, "Wrong offset for file_size in Entry.");
class DirectoryBackend : NonCopyable {
public:
DirectoryBackend() {}
virtual ~DirectoryBackend() {}
/**
* List files contained in the directory
* @param count Number of entries to return at once in entries
* @param entries Buffer to read data into
* @return Number of entries listed
*/
virtual u64 Read(const u64 count, Entry* entries) = 0;
/// Returns the number of entries still left to read.
virtual u64 GetEntryCount() const = 0;
/**
* Close the directory
* @return true if the directory closed correctly
*/
virtual bool Close() const = 0;
};
} // namespace FileSys

View File

@@ -119,6 +119,9 @@ VirtualDir ExtractRomFS(VirtualFile file, RomFSExtractionType type) {
VirtualDir out = std::move(root);
if (type == RomFSExtractionType::SingleDiscard)
return out->GetSubdirectories().front();
while (out->GetSubdirectories().size() == 1 && out->GetFiles().empty()) {
if (out->GetSubdirectories().front()->GetName() == "data" &&
type == RomFSExtractionType::Truncated)

View File

@@ -33,8 +33,9 @@ struct IVFCHeader {
static_assert(sizeof(IVFCHeader) == 0xE0, "IVFCHeader has incorrect size.");
enum class RomFSExtractionType {
Full, // Includes data directory
Truncated, // Traverses into data directory
Full, // Includes data directory
Truncated, // Traverses into data directory
SingleDiscard, // Traverses into the first subdirectory of root
};
// Converts a RomFS binary blob to VFS Filesystem

View File

@@ -47,7 +47,7 @@ std::size_t VectorVfsFile::Write(const u8* data_, std::size_t length, std::size_
if (offset + length > data.size())
data.resize(offset + length);
const auto write = std::min(length, data.size() - offset);
std::memcpy(data.data(), data_, write);
std::memcpy(data.data() + offset, data_, write);
return write;
}

View File

@@ -0,0 +1,24 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/logging/log.h"
#include "core/frontend/applets/web_browser.h"
namespace Core::Frontend {
WebBrowserApplet::~WebBrowserApplet() = default;
DefaultWebBrowserApplet::~DefaultWebBrowserApplet() = default;
void DefaultWebBrowserApplet::OpenPage(std::string_view filename,
std::function<void()> unpack_romfs_callback,
std::function<void()> finished_callback) {
LOG_INFO(Service_AM,
"(STUBBED) called - No suitable web browser implementation found to open website page "
"at '{}'!",
filename);
finished_callback();
}
} // namespace Core::Frontend

View File

@@ -0,0 +1,28 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <functional>
#include <string_view>
namespace Core::Frontend {
class WebBrowserApplet {
public:
virtual ~WebBrowserApplet();
virtual void OpenPage(std::string_view url, std::function<void()> unpack_romfs_callback,
std::function<void()> finished_callback) = 0;
};
class DefaultWebBrowserApplet final : public WebBrowserApplet {
public:
~DefaultWebBrowserApplet() override;
void OpenPage(std::string_view url, std::function<void()> unpack_romfs_callback,
std::function<void()> finished_callback) override;
};
} // namespace Core::Frontend

View File

@@ -67,7 +67,7 @@ static bool IsWithinTouchscreen(const Layout::FramebufferLayout& layout, unsigne
framebuffer_x >= layout.screen.left && framebuffer_x < layout.screen.right);
}
std::tuple<unsigned, unsigned> EmuWindow::ClipToTouchScreen(unsigned new_x, unsigned new_y) {
std::tuple<unsigned, unsigned> EmuWindow::ClipToTouchScreen(unsigned new_x, unsigned new_y) const {
new_x = std::max(new_x, framebuffer_layout.screen.left);
new_x = std::min(new_x, framebuffer_layout.screen.right - 1);

View File

@@ -166,7 +166,7 @@ private:
/**
* Clip the provided coordinates to be inside the touchscreen area.
*/
std::tuple<unsigned, unsigned> ClipToTouchScreen(unsigned new_x, unsigned new_y);
std::tuple<unsigned, unsigned> ClipToTouchScreen(unsigned new_x, unsigned new_y) const;
};
} // namespace Core::Frontend

View File

@@ -12,12 +12,12 @@ namespace Layout {
// Finds the largest size subrectangle contained in window area that is confined to the aspect ratio
template <class T>
static MathUtil::Rectangle<T> maxRectangle(MathUtil::Rectangle<T> window_area,
float screen_aspect_ratio) {
static Common::Rectangle<T> MaxRectangle(Common::Rectangle<T> window_area,
float screen_aspect_ratio) {
float scale = std::min(static_cast<float>(window_area.GetWidth()),
window_area.GetHeight() / screen_aspect_ratio);
return MathUtil::Rectangle<T>{0, 0, static_cast<T>(std::round(scale)),
static_cast<T>(std::round(scale * screen_aspect_ratio))};
return Common::Rectangle<T>{0, 0, static_cast<T>(std::round(scale)),
static_cast<T>(std::round(scale * screen_aspect_ratio))};
}
FramebufferLayout DefaultFrameLayout(unsigned width, unsigned height) {
@@ -29,8 +29,8 @@ FramebufferLayout DefaultFrameLayout(unsigned width, unsigned height) {
const float emulation_aspect_ratio{static_cast<float>(ScreenUndocked::Height) /
ScreenUndocked::Width};
MathUtil::Rectangle<unsigned> screen_window_area{0, 0, width, height};
MathUtil::Rectangle<unsigned> screen = maxRectangle(screen_window_area, emulation_aspect_ratio);
Common::Rectangle<unsigned> screen_window_area{0, 0, width, height};
Common::Rectangle<unsigned> screen = MaxRectangle(screen_window_area, emulation_aspect_ratio);
float window_aspect_ratio = static_cast<float>(height) / width;

View File

@@ -16,7 +16,7 @@ struct FramebufferLayout {
unsigned width{ScreenUndocked::Width};
unsigned height{ScreenUndocked::Height};
MathUtil::Rectangle<unsigned> screen;
Common::Rectangle<unsigned> screen;
/**
* Returns the ration of pixel size of the screen, compared to the native size of the undocked

View File

@@ -124,7 +124,7 @@ using AnalogDevice = InputDevice<std::tuple<float, float>>;
* Orientation is determined by right-hand rule.
* Units: deg/sec
*/
using MotionDevice = InputDevice<std::tuple<Math::Vec3<float>, Math::Vec3<float>>>;
using MotionDevice = InputDevice<std::tuple<Common::Vec3<float>, Common::Vec3<float>>>;
/**
* A touch device is an input device that returns a tuple of two floats and a bool. The floats are

View File

@@ -0,0 +1,18 @@
// Copyright 2019 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "core/frontend/emu_window.h"
#include "core/frontend/scope_acquire_window_context.h"
namespace Core::Frontend {
ScopeAcquireWindowContext::ScopeAcquireWindowContext(Core::Frontend::EmuWindow& emu_window_)
: emu_window{emu_window_} {
emu_window.MakeCurrent();
}
ScopeAcquireWindowContext::~ScopeAcquireWindowContext() {
emu_window.DoneCurrent();
}
} // namespace Core::Frontend

View File

@@ -0,0 +1,23 @@
// Copyright 2019 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "common/common_types.h"
namespace Core::Frontend {
class EmuWindow;
/// Helper class to acquire/release window context within a given scope
class ScopeAcquireWindowContext : NonCopyable {
public:
explicit ScopeAcquireWindowContext(Core::Frontend::EmuWindow& window);
~ScopeAcquireWindowContext();
private:
Core::Frontend::EmuWindow& emu_window;
};
} // namespace Core::Frontend

View File

@@ -507,8 +507,11 @@ static void RemoveBreakpoint(BreakpointType type, VAddr addr) {
LOG_DEBUG(Debug_GDBStub, "gdb: removed a breakpoint: {:016X} bytes at {:016X} of type {}",
bp->second.len, bp->second.addr, static_cast<int>(type));
Memory::WriteBlock(bp->second.addr, bp->second.inst.data(), bp->second.inst.size());
Core::System::GetInstance().InvalidateCpuInstructionCaches();
if (type == BreakpointType::Execute) {
Memory::WriteBlock(bp->second.addr, bp->second.inst.data(), bp->second.inst.size());
Core::System::GetInstance().InvalidateCpuInstructionCaches();
}
p.erase(addr);
}
@@ -1057,9 +1060,12 @@ static bool CommitBreakpoint(BreakpointType type, VAddr addr, u64 len) {
breakpoint.addr = addr;
breakpoint.len = len;
Memory::ReadBlock(addr, breakpoint.inst.data(), breakpoint.inst.size());
static constexpr std::array<u8, 4> btrap{0x00, 0x7d, 0x20, 0xd4};
Memory::WriteBlock(addr, btrap.data(), btrap.size());
Core::System::GetInstance().InvalidateCpuInstructionCaches();
if (type == BreakpointType::Execute) {
Memory::WriteBlock(addr, btrap.data(), btrap.size());
Core::System::GetInstance().InvalidateCpuInstructionCaches();
}
p.insert({addr, breakpoint});
LOG_DEBUG(Debug_GDBStub, "gdb: added {} breakpoint: {:016X} bytes at {:016X}",

View File

@@ -4,10 +4,10 @@
#pragma once
#include "common/bit_field.h"
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/swap.h"
#include "core/hle/kernel/errors.h"
#include "core/memory.h"
namespace IPC {

View File

@@ -216,6 +216,11 @@ private:
/// Push ///
template <>
inline void ResponseBuilder::Push(s32 value) {
cmdbuf[index++] = static_cast<u32>(value);
}
template <>
inline void ResponseBuilder::Push(u32 value) {
cmdbuf[index++] = value;
@@ -234,6 +239,22 @@ inline void ResponseBuilder::Push(ResultCode value) {
Push<u32>(0);
}
template <>
inline void ResponseBuilder::Push(s8 value) {
PushRaw(value);
}
template <>
inline void ResponseBuilder::Push(s16 value) {
PushRaw(value);
}
template <>
inline void ResponseBuilder::Push(s64 value) {
Push(static_cast<u32>(value));
Push(static_cast<u32>(value >> 32));
}
template <>
inline void ResponseBuilder::Push(u8 value) {
PushRaw(value);
@@ -329,7 +350,7 @@ public:
template <class T>
std::shared_ptr<T> PopIpcInterface() {
ASSERT(context->Session()->IsDomain());
ASSERT(context->GetDomainMessageHeader()->input_object_count > 0);
ASSERT(context->GetDomainMessageHeader().input_object_count > 0);
return context->GetDomainRequestHandler<T>(Pop<u32>() - 1);
}
};

View File

@@ -9,6 +9,7 @@
#include "common/common_types.h"
#include "core/core.h"
#include "core/core_cpu.h"
#include "core/hle/kernel/address_arbiter.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/process.h"
@@ -18,32 +19,143 @@
#include "core/memory.h"
namespace Kernel {
namespace AddressArbiter {
namespace {
// Wake up num_to_wake (or all) threads in a vector.
void WakeThreads(const std::vector<SharedPtr<Thread>>& waiting_threads, s32 num_to_wake) {
// Only process up to 'target' threads, unless 'target' is <= 0, in which case process
// them all.
std::size_t last = waiting_threads.size();
if (num_to_wake > 0) {
last = num_to_wake;
}
// Performs actual address waiting logic.
static ResultCode WaitForAddress(VAddr address, s64 timeout) {
SharedPtr<Thread> current_thread = GetCurrentThread();
// Signal the waiting threads.
for (std::size_t i = 0; i < last; i++) {
ASSERT(waiting_threads[i]->GetStatus() == ThreadStatus::WaitArb);
waiting_threads[i]->SetWaitSynchronizationResult(RESULT_SUCCESS);
waiting_threads[i]->SetArbiterWaitAddress(0);
waiting_threads[i]->ResumeFromWait();
}
}
} // Anonymous namespace
AddressArbiter::AddressArbiter(Core::System& system) : system{system} {}
AddressArbiter::~AddressArbiter() = default;
ResultCode AddressArbiter::SignalToAddress(VAddr address, s32 num_to_wake) {
const std::vector<SharedPtr<Thread>> waiting_threads = GetThreadsWaitingOnAddress(address);
WakeThreads(waiting_threads, num_to_wake);
return RESULT_SUCCESS;
}
ResultCode AddressArbiter::IncrementAndSignalToAddressIfEqual(VAddr address, s32 value,
s32 num_to_wake) {
// Ensure that we can write to the address.
if (!Memory::IsValidVirtualAddress(address)) {
return ERR_INVALID_ADDRESS_STATE;
}
if (static_cast<s32>(Memory::Read32(address)) != value) {
return ERR_INVALID_STATE;
}
Memory::Write32(address, static_cast<u32>(value + 1));
return SignalToAddress(address, num_to_wake);
}
ResultCode AddressArbiter::ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 value,
s32 num_to_wake) {
// Ensure that we can write to the address.
if (!Memory::IsValidVirtualAddress(address)) {
return ERR_INVALID_ADDRESS_STATE;
}
// Get threads waiting on the address.
const std::vector<SharedPtr<Thread>> waiting_threads = GetThreadsWaitingOnAddress(address);
// Determine the modified value depending on the waiting count.
s32 updated_value;
if (waiting_threads.empty()) {
updated_value = value - 1;
} else if (num_to_wake <= 0 || waiting_threads.size() <= static_cast<u32>(num_to_wake)) {
updated_value = value + 1;
} else {
updated_value = value;
}
if (static_cast<s32>(Memory::Read32(address)) != value) {
return ERR_INVALID_STATE;
}
Memory::Write32(address, static_cast<u32>(updated_value));
WakeThreads(waiting_threads, num_to_wake);
return RESULT_SUCCESS;
}
ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout,
bool should_decrement) {
// Ensure that we can read the address.
if (!Memory::IsValidVirtualAddress(address)) {
return ERR_INVALID_ADDRESS_STATE;
}
const s32 cur_value = static_cast<s32>(Memory::Read32(address));
if (cur_value >= value) {
return ERR_INVALID_STATE;
}
if (should_decrement) {
Memory::Write32(address, static_cast<u32>(cur_value - 1));
}
// Short-circuit without rescheduling, if timeout is zero.
if (timeout == 0) {
return RESULT_TIMEOUT;
}
return WaitForAddress(address, timeout);
}
ResultCode AddressArbiter::WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout) {
// Ensure that we can read the address.
if (!Memory::IsValidVirtualAddress(address)) {
return ERR_INVALID_ADDRESS_STATE;
}
// Only wait for the address if equal.
if (static_cast<s32>(Memory::Read32(address)) != value) {
return ERR_INVALID_STATE;
}
// Short-circuit without rescheduling, if timeout is zero.
if (timeout == 0) {
return RESULT_TIMEOUT;
}
return WaitForAddress(address, timeout);
}
ResultCode AddressArbiter::WaitForAddress(VAddr address, s64 timeout) {
SharedPtr<Thread> current_thread = system.CurrentScheduler().GetCurrentThread();
current_thread->SetArbiterWaitAddress(address);
current_thread->SetStatus(ThreadStatus::WaitArb);
current_thread->InvalidateWakeupCallback();
current_thread->WakeAfterDelay(timeout);
Core::System::GetInstance().CpuCore(current_thread->GetProcessorID()).PrepareReschedule();
system.CpuCore(current_thread->GetProcessorID()).PrepareReschedule();
return RESULT_TIMEOUT;
}
// Gets the threads waiting on an address.
static std::vector<SharedPtr<Thread>> GetThreadsWaitingOnAddress(VAddr address) {
const auto RetrieveWaitingThreads = [](std::size_t core_index,
std::vector<SharedPtr<Thread>>& waiting_threads,
VAddr arb_addr) {
const auto& scheduler = Core::System::GetInstance().Scheduler(core_index);
std::vector<SharedPtr<Thread>> AddressArbiter::GetThreadsWaitingOnAddress(VAddr address) const {
const auto RetrieveWaitingThreads = [this](std::size_t core_index,
std::vector<SharedPtr<Thread>>& waiting_threads,
VAddr arb_addr) {
const auto& scheduler = system.Scheduler(core_index);
const auto& thread_list = scheduler.GetThreadList();
for (const auto& thread : thread_list) {
if (thread->GetArbiterWaitAddress() == arb_addr)
if (thread->GetArbiterWaitAddress() == arb_addr) {
waiting_threads.push_back(thread);
}
}
};
@@ -62,119 +174,4 @@ static std::vector<SharedPtr<Thread>> GetThreadsWaitingOnAddress(VAddr address)
return threads;
}
// Wake up num_to_wake (or all) threads in a vector.
static void WakeThreads(std::vector<SharedPtr<Thread>>& waiting_threads, s32 num_to_wake) {
// Only process up to 'target' threads, unless 'target' is <= 0, in which case process
// them all.
std::size_t last = waiting_threads.size();
if (num_to_wake > 0)
last = num_to_wake;
// Signal the waiting threads.
for (std::size_t i = 0; i < last; i++) {
ASSERT(waiting_threads[i]->GetStatus() == ThreadStatus::WaitArb);
waiting_threads[i]->SetWaitSynchronizationResult(RESULT_SUCCESS);
waiting_threads[i]->SetArbiterWaitAddress(0);
waiting_threads[i]->ResumeFromWait();
}
}
// Signals an address being waited on.
ResultCode SignalToAddress(VAddr address, s32 num_to_wake) {
std::vector<SharedPtr<Thread>> waiting_threads = GetThreadsWaitingOnAddress(address);
WakeThreads(waiting_threads, num_to_wake);
return RESULT_SUCCESS;
}
// Signals an address being waited on and increments its value if equal to the value argument.
ResultCode IncrementAndSignalToAddressIfEqual(VAddr address, s32 value, s32 num_to_wake) {
// Ensure that we can write to the address.
if (!Memory::IsValidVirtualAddress(address)) {
return ERR_INVALID_ADDRESS_STATE;
}
if (static_cast<s32>(Memory::Read32(address)) == value) {
Memory::Write32(address, static_cast<u32>(value + 1));
} else {
return ERR_INVALID_STATE;
}
return SignalToAddress(address, num_to_wake);
}
// Signals an address being waited on and modifies its value based on waiting thread count if equal
// to the value argument.
ResultCode ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 value,
s32 num_to_wake) {
// Ensure that we can write to the address.
if (!Memory::IsValidVirtualAddress(address)) {
return ERR_INVALID_ADDRESS_STATE;
}
// Get threads waiting on the address.
std::vector<SharedPtr<Thread>> waiting_threads = GetThreadsWaitingOnAddress(address);
// Determine the modified value depending on the waiting count.
s32 updated_value;
if (waiting_threads.empty()) {
updated_value = value - 1;
} else if (num_to_wake <= 0 || waiting_threads.size() <= static_cast<u32>(num_to_wake)) {
updated_value = value + 1;
} else {
updated_value = value;
}
if (static_cast<s32>(Memory::Read32(address)) == value) {
Memory::Write32(address, static_cast<u32>(updated_value));
} else {
return ERR_INVALID_STATE;
}
WakeThreads(waiting_threads, num_to_wake);
return RESULT_SUCCESS;
}
// Waits on an address if the value passed is less than the argument value, optionally decrementing.
ResultCode WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout, bool should_decrement) {
// Ensure that we can read the address.
if (!Memory::IsValidVirtualAddress(address)) {
return ERR_INVALID_ADDRESS_STATE;
}
s32 cur_value = static_cast<s32>(Memory::Read32(address));
if (cur_value < value) {
if (should_decrement) {
Memory::Write32(address, static_cast<u32>(cur_value - 1));
}
} else {
return ERR_INVALID_STATE;
}
// Short-circuit without rescheduling, if timeout is zero.
if (timeout == 0) {
return RESULT_TIMEOUT;
}
return WaitForAddress(address, timeout);
}
// Waits on an address if the value passed is equal to the argument value.
ResultCode WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout) {
// Ensure that we can read the address.
if (!Memory::IsValidVirtualAddress(address)) {
return ERR_INVALID_ADDRESS_STATE;
}
// Only wait for the address if equal.
if (static_cast<s32>(Memory::Read32(address)) != value) {
return ERR_INVALID_STATE;
}
// Short-circuit without rescheduling, if timeout is zero.
if (timeout == 0) {
return RESULT_TIMEOUT;
}
return WaitForAddress(address, timeout);
}
} // namespace AddressArbiter
} // namespace Kernel

View File

@@ -5,30 +5,68 @@
#pragma once
#include "common/common_types.h"
#include "core/hle/kernel/address_arbiter.h"
union ResultCode;
namespace Core {
class System;
}
namespace Kernel {
namespace AddressArbiter {
enum class ArbitrationType {
WaitIfLessThan = 0,
DecrementAndWaitIfLessThan = 1,
WaitIfEqual = 2,
class Thread;
class AddressArbiter {
public:
enum class ArbitrationType {
WaitIfLessThan = 0,
DecrementAndWaitIfLessThan = 1,
WaitIfEqual = 2,
};
enum class SignalType {
Signal = 0,
IncrementAndSignalIfEqual = 1,
ModifyByWaitingCountAndSignalIfEqual = 2,
};
explicit AddressArbiter(Core::System& system);
~AddressArbiter();
AddressArbiter(const AddressArbiter&) = delete;
AddressArbiter& operator=(const AddressArbiter&) = delete;
AddressArbiter(AddressArbiter&&) = default;
AddressArbiter& operator=(AddressArbiter&&) = delete;
/// Signals an address being waited on.
ResultCode SignalToAddress(VAddr address, s32 num_to_wake);
/// Signals an address being waited on and increments its value if equal to the value argument.
ResultCode IncrementAndSignalToAddressIfEqual(VAddr address, s32 value, s32 num_to_wake);
/// Signals an address being waited on and modifies its value based on waiting thread count if
/// equal to the value argument.
ResultCode ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 value,
s32 num_to_wake);
/// Waits on an address if the value passed is less than the argument value,
/// optionally decrementing.
ResultCode WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout,
bool should_decrement);
/// Waits on an address if the value passed is equal to the argument value.
ResultCode WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout);
private:
// Waits on the given address with a timeout in nanoseconds
ResultCode WaitForAddress(VAddr address, s64 timeout);
// Gets the threads waiting on an address.
std::vector<SharedPtr<Thread>> GetThreadsWaitingOnAddress(VAddr address) const;
Core::System& system;
};
enum class SignalType {
Signal = 0,
IncrementAndSignalIfEqual = 1,
ModifyByWaitingCountAndSignalIfEqual = 2,
};
ResultCode SignalToAddress(VAddr address, s32 num_to_wake);
ResultCode IncrementAndSignalToAddressIfEqual(VAddr address, s32 value, s32 num_to_wake);
ResultCode ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 value, s32 num_to_wake);
ResultCode WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout, bool should_decrement);
ResultCode WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout);
} // namespace AddressArbiter
} // namespace Kernel

View File

@@ -33,10 +33,11 @@ ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() {
// Create a new session pair, let the created sessions inherit the parent port's HLE handler.
auto sessions = ServerSession::CreateSessionPair(kernel, server_port->GetName(), this);
if (server_port->hle_handler)
server_port->hle_handler->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions));
else
server_port->pending_sessions.push_back(std::get<SharedPtr<ServerSession>>(sessions));
if (server_port->HasHLEHandler()) {
server_port->GetHLEHandler()->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions));
} else {
server_port->AppendPendingSession(std::get<SharedPtr<ServerSession>>(sessions));
}
// Wake the threads waiting on the ServerPort
server_port->WakeupAllWaitingThreads();

View File

@@ -17,21 +17,11 @@ ClientSession::~ClientSession() {
// This destructor will be called automatically when the last ClientSession handle is closed by
// the emulated application.
// Local references to ServerSession and SessionRequestHandler are necessary to guarantee they
// A local reference to the ServerSession is necessary to guarantee it
// will be kept alive until after ClientDisconnected() returns.
SharedPtr<ServerSession> server = parent->server;
if (server) {
std::shared_ptr<SessionRequestHandler> hle_handler = server->hle_handler;
if (hle_handler)
hle_handler->ClientDisconnected(server);
// TODO(Subv): Force a wake up of all the ServerSession's waiting threads and set
// their WaitSynchronization result to 0xC920181A.
// Clean up the list of client threads with pending requests, they are unneeded now that the
// client endpoint is closed.
server->pending_requesting_threads.clear();
server->currently_handling = nullptr;
server->ClientDisconnected();
}
parent->client = nullptr;

View File

@@ -36,14 +36,15 @@ public:
ResultCode SendSyncRequest(SharedPtr<Thread> thread);
std::string name; ///< Name of client port (optional)
private:
explicit ClientSession(KernelCore& kernel);
~ClientSession() override;
/// The parent session, which links to the server endpoint.
std::shared_ptr<Session> parent;
private:
explicit ClientSession(KernelCore& kernel);
~ClientSession() override;
/// Name of the client session (optional)
std::string name;
};
} // namespace Kernel

View File

@@ -14,6 +14,7 @@ constexpr ResultCode ERR_MAX_CONNECTIONS_REACHED{ErrorModule::Kernel, 7};
constexpr ResultCode ERR_INVALID_CAPABILITY_DESCRIPTOR{ErrorModule::Kernel, 14};
constexpr ResultCode ERR_INVALID_SIZE{ErrorModule::Kernel, 101};
constexpr ResultCode ERR_INVALID_ADDRESS{ErrorModule::Kernel, 102};
constexpr ResultCode ERR_OUT_OF_MEMORY{ErrorModule::Kernel, 104};
constexpr ResultCode ERR_HANDLE_TABLE_FULL{ErrorModule::Kernel, 105};
constexpr ResultCode ERR_INVALID_ADDRESS_STATE{ErrorModule::Kernel, 106};
constexpr ResultCode ERR_INVALID_MEMORY_PERMISSIONS{ErrorModule::Kernel, 108};

View File

@@ -14,32 +14,47 @@
namespace Kernel {
namespace {
constexpr u16 GetSlot(Handle handle) {
return handle >> 15;
return static_cast<u16>(handle >> 15);
}
constexpr u16 GetGeneration(Handle handle) {
return handle & 0x7FFF;
return static_cast<u16>(handle & 0x7FFF);
}
} // Anonymous namespace
HandleTable::HandleTable() {
next_generation = 1;
Clear();
}
HandleTable::~HandleTable() = default;
ResultCode HandleTable::SetSize(s32 handle_table_size) {
if (static_cast<u32>(handle_table_size) > MAX_COUNT) {
return ERR_OUT_OF_MEMORY;
}
// Values less than or equal to zero indicate to use the maximum allowable
// size for the handle table in the actual kernel, so we ignore the given
// value in that case, since we assume this by default unless this function
// is called.
if (handle_table_size > 0) {
table_size = static_cast<u16>(handle_table_size);
}
return RESULT_SUCCESS;
}
ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
DEBUG_ASSERT(obj != nullptr);
u16 slot = next_free_slot;
if (slot >= generations.size()) {
const u16 slot = next_free_slot;
if (slot >= table_size) {
LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use.");
return ERR_HANDLE_TABLE_FULL;
}
next_free_slot = generations[slot];
u16 generation = next_generation++;
const u16 generation = next_generation++;
// Overflow count so it fits in the 15 bits dedicated to the generation in the handle.
// Horizon OS uses zero to represent an invalid handle, so skip to 1.
@@ -64,10 +79,11 @@ ResultVal<Handle> HandleTable::Duplicate(Handle handle) {
}
ResultCode HandleTable::Close(Handle handle) {
if (!IsValid(handle))
if (!IsValid(handle)) {
return ERR_INVALID_HANDLE;
}
u16 slot = GetSlot(handle);
const u16 slot = GetSlot(handle);
objects[slot] = nullptr;
@@ -77,10 +93,10 @@ ResultCode HandleTable::Close(Handle handle) {
}
bool HandleTable::IsValid(Handle handle) const {
std::size_t slot = GetSlot(handle);
u16 generation = GetGeneration(handle);
const std::size_t slot = GetSlot(handle);
const u16 generation = GetGeneration(handle);
return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation;
return slot < table_size && objects[slot] != nullptr && generations[slot] == generation;
}
SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const {
@@ -97,7 +113,7 @@ SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const {
}
void HandleTable::Clear() {
for (u16 i = 0; i < MAX_COUNT; ++i) {
for (u16 i = 0; i < table_size; ++i) {
generations[i] = i + 1;
objects[i] = nullptr;
}

View File

@@ -49,6 +49,20 @@ public:
HandleTable();
~HandleTable();
/**
* Sets the number of handles that may be in use at one time
* for this handle table.
*
* @param handle_table_size The desired size to limit the handle table to.
*
* @returns an error code indicating if initialization was successful.
* If initialization was not successful, then ERR_OUT_OF_MEMORY
* will be returned.
*
* @pre handle_table_size must be within the range [0, 1024]
*/
ResultCode SetSize(s32 handle_table_size);
/**
* Allocates a handle for the given object.
* @return The created Handle or one of the following errors:
@@ -103,14 +117,21 @@ private:
*/
std::array<u16, MAX_COUNT> generations;
/**
* The limited size of the handle table. This can be specified by process
* capabilities in order to restrict the overall number of handles that
* can be created in a process instance
*/
u16 table_size = static_cast<u16>(MAX_COUNT);
/**
* Global counter of the number of created handles. Stored in `generations` when a handle is
* created, and wraps around to 1 when it hits 0x8000.
*/
u16 next_generation;
u16 next_generation = 1;
/// Head of the free slots linked list.
u16 next_free_slot;
u16 next_free_slot = 0;
};
} // namespace Kernel

View File

@@ -86,7 +86,7 @@ HLERequestContext::~HLERequestContext() = default;
void HLERequestContext::ParseCommandBuffer(const HandleTable& handle_table, u32_le* src_cmdbuf,
bool incoming) {
IPC::RequestParser rp(src_cmdbuf);
command_header = std::make_shared<IPC::CommandHeader>(rp.PopRaw<IPC::CommandHeader>());
command_header = rp.PopRaw<IPC::CommandHeader>();
if (command_header->type == IPC::CommandType::Close) {
// Close does not populate the rest of the IPC header
@@ -95,8 +95,7 @@ void HLERequestContext::ParseCommandBuffer(const HandleTable& handle_table, u32_
// If handle descriptor is present, add size of it
if (command_header->enable_handle_descriptor) {
handle_descriptor_header =
std::make_shared<IPC::HandleDescriptorHeader>(rp.PopRaw<IPC::HandleDescriptorHeader>());
handle_descriptor_header = rp.PopRaw<IPC::HandleDescriptorHeader>();
if (handle_descriptor_header->send_current_pid) {
rp.Skip(2, false);
}
@@ -140,16 +139,15 @@ void HLERequestContext::ParseCommandBuffer(const HandleTable& handle_table, u32_
// If this is an incoming message, only CommandType "Request" has a domain header
// All outgoing domain messages have the domain header, if only incoming has it
if (incoming || domain_message_header) {
domain_message_header =
std::make_shared<IPC::DomainMessageHeader>(rp.PopRaw<IPC::DomainMessageHeader>());
domain_message_header = rp.PopRaw<IPC::DomainMessageHeader>();
} else {
if (Session()->IsDomain())
if (Session()->IsDomain()) {
LOG_WARNING(IPC, "Domain request has no DomainMessageHeader!");
}
}
}
data_payload_header =
std::make_shared<IPC::DataPayloadHeader>(rp.PopRaw<IPC::DataPayloadHeader>());
data_payload_header = rp.PopRaw<IPC::DataPayloadHeader>();
data_payload_offset = rp.GetCurrentOffset();
@@ -264,11 +262,11 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(Thread& thread) {
// Write the domain objects to the command buffer, these go after the raw untranslated data.
// TODO(Subv): This completely ignores C buffers.
std::size_t domain_offset = size - domain_message_header->num_objects;
auto& request_handlers = server_session->domain_request_handlers;
for (auto& object : domain_objects) {
request_handlers.emplace_back(object);
dst_cmdbuf[domain_offset++] = static_cast<u32_le>(request_handlers.size());
for (const auto& object : domain_objects) {
server_session->AppendDomainRequestHandler(object);
dst_cmdbuf[domain_offset++] =
static_cast<u32_le>(server_session->NumDomainRequestHandlers());
}
}

View File

@@ -6,6 +6,7 @@
#include <array>
#include <memory>
#include <optional>
#include <string>
#include <type_traits>
#include <vector>
@@ -15,6 +16,8 @@
#include "core/hle/ipc.h"
#include "core/hle/kernel/object.h"
union ResultCode;
namespace Service {
class ServiceFrameworkBase;
}
@@ -166,12 +169,12 @@ public:
return buffer_c_desciptors;
}
const IPC::DomainMessageHeader* GetDomainMessageHeader() const {
return domain_message_header.get();
const IPC::DomainMessageHeader& GetDomainMessageHeader() const {
return domain_message_header.value();
}
bool HasDomainMessageHeader() const {
return domain_message_header != nullptr;
return domain_message_header.has_value();
}
/// Helper function to read a buffer using the appropriate buffer descriptor
@@ -208,14 +211,12 @@ public:
template <typename T>
SharedPtr<T> GetCopyObject(std::size_t index) {
ASSERT(index < copy_objects.size());
return DynamicObjectCast<T>(copy_objects[index]);
return DynamicObjectCast<T>(copy_objects.at(index));
}
template <typename T>
SharedPtr<T> GetMoveObject(std::size_t index) {
ASSERT(index < move_objects.size());
return DynamicObjectCast<T>(move_objects[index]);
return DynamicObjectCast<T>(move_objects.at(index));
}
void AddMoveObject(SharedPtr<Object> object) {
@@ -232,7 +233,7 @@ public:
template <typename T>
std::shared_ptr<T> GetDomainRequestHandler(std::size_t index) const {
return std::static_pointer_cast<T>(domain_request_handlers[index]);
return std::static_pointer_cast<T>(domain_request_handlers.at(index));
}
void SetDomainRequestHandlers(
@@ -272,10 +273,10 @@ private:
boost::container::small_vector<SharedPtr<Object>, 8> copy_objects;
boost::container::small_vector<std::shared_ptr<SessionRequestHandler>, 8> domain_objects;
std::shared_ptr<IPC::CommandHeader> command_header;
std::shared_ptr<IPC::HandleDescriptorHeader> handle_descriptor_header;
std::shared_ptr<IPC::DataPayloadHeader> data_payload_header;
std::shared_ptr<IPC::DomainMessageHeader> domain_message_header;
std::optional<IPC::CommandHeader> command_header;
std::optional<IPC::HandleDescriptorHeader> handle_descriptor_header;
std::optional<IPC::DataPayloadHeader> data_payload_header;
std::optional<IPC::DomainMessageHeader> domain_message_header;
std::vector<IPC::BufferDescriptorX> buffer_x_desciptors;
std::vector<IPC::BufferDescriptorABW> buffer_a_desciptors;
std::vector<IPC::BufferDescriptorABW> buffer_b_desciptors;

View File

@@ -12,13 +12,13 @@
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/kernel/address_arbiter.h"
#include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/timer.h"
#include "core/hle/lock.h"
#include "core/hle/result.h"
@@ -86,27 +86,14 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] int cycles_
}
}
/// The timer callback event, called when a timer is fired
static void TimerCallback(u64 timer_handle, int cycles_late) {
const auto proper_handle = static_cast<Handle>(timer_handle);
const auto& system = Core::System::GetInstance();
SharedPtr<Timer> timer = system.Kernel().RetrieveTimerFromCallbackHandleTable(proper_handle);
if (timer == nullptr) {
LOG_CRITICAL(Kernel, "Callback fired for invalid timer {:016X}", timer_handle);
return;
}
timer->Signal(cycles_late);
}
struct KernelCore::Impl {
explicit Impl(Core::System& system) : address_arbiter{system}, system{system} {}
void Initialize(KernelCore& kernel) {
Shutdown();
InitializeSystemResourceLimit(kernel);
InitializeThreads();
InitializeTimers();
}
void Shutdown() {
@@ -122,9 +109,6 @@ struct KernelCore::Impl {
thread_wakeup_callback_handle_table.Clear();
thread_wakeup_event_type = nullptr;
timer_callback_handle_table.Clear();
timer_callback_event_type = nullptr;
named_ports.clear();
}
@@ -143,12 +127,7 @@ struct KernelCore::Impl {
void InitializeThreads() {
thread_wakeup_event_type =
CoreTiming::RegisterEvent("ThreadWakeupCallback", ThreadWakeupCallback);
}
void InitializeTimers() {
timer_callback_handle_table.Clear();
timer_callback_event_type = CoreTiming::RegisterEvent("TimerCallback", TimerCallback);
system.CoreTiming().RegisterEvent("ThreadWakeupCallback", ThreadWakeupCallback);
}
std::atomic<u32> next_object_id{0};
@@ -159,15 +138,11 @@ struct KernelCore::Impl {
std::vector<SharedPtr<Process>> process_list;
Process* current_process = nullptr;
Kernel::AddressArbiter address_arbiter;
SharedPtr<ResourceLimit> system_resource_limit;
/// The event type of the generic timer callback event
CoreTiming::EventType* timer_callback_event_type = nullptr;
// TODO(yuriks): This can be removed if Timer objects are explicitly pooled in the future,
// allowing us to simply use a pool index or similar.
Kernel::HandleTable timer_callback_handle_table;
CoreTiming::EventType* thread_wakeup_event_type = nullptr;
Core::Timing::EventType* thread_wakeup_event_type = nullptr;
// TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future,
// allowing us to simply use a pool index or similar.
Kernel::HandleTable thread_wakeup_callback_handle_table;
@@ -175,9 +150,12 @@ struct KernelCore::Impl {
/// Map of named ports managed by the kernel, which can be retrieved using
/// the ConnectToPort SVC.
NamedPortTable named_ports;
// System context
Core::System& system;
};
KernelCore::KernelCore() : impl{std::make_unique<Impl>()} {}
KernelCore::KernelCore(Core::System& system) : impl{std::make_unique<Impl>(system)} {}
KernelCore::~KernelCore() {
Shutdown();
}
@@ -198,10 +176,6 @@ SharedPtr<Thread> KernelCore::RetrieveThreadFromWakeupCallbackHandleTable(Handle
return impl->thread_wakeup_callback_handle_table.Get<Thread>(handle);
}
SharedPtr<Timer> KernelCore::RetrieveTimerFromCallbackHandleTable(Handle handle) const {
return impl->timer_callback_handle_table.Get<Timer>(handle);
}
void KernelCore::AppendNewProcess(SharedPtr<Process> process) {
impl->process_list.push_back(std::move(process));
}
@@ -218,6 +192,14 @@ const Process* KernelCore::CurrentProcess() const {
return impl->current_process;
}
AddressArbiter& KernelCore::AddressArbiter() {
return impl->address_arbiter;
}
const AddressArbiter& KernelCore::AddressArbiter() const {
return impl->address_arbiter;
}
void KernelCore::AddNamedPort(std::string name, SharedPtr<ClientPort> port) {
impl->named_ports.emplace(std::move(name), std::move(port));
}
@@ -247,18 +229,10 @@ u64 KernelCore::CreateNewProcessID() {
return impl->next_process_id++;
}
ResultVal<Handle> KernelCore::CreateTimerCallbackHandle(const SharedPtr<Timer>& timer) {
return impl->timer_callback_handle_table.Create(timer);
}
CoreTiming::EventType* KernelCore::ThreadWakeupCallbackEventType() const {
Core::Timing::EventType* KernelCore::ThreadWakeupCallbackEventType() const {
return impl->thread_wakeup_event_type;
}
CoreTiming::EventType* KernelCore::TimerCallbackEventType() const {
return impl->timer_callback_event_type;
}
Kernel::HandleTable& KernelCore::ThreadWakeupCallbackHandleTable() {
return impl->thread_wakeup_callback_handle_table;
}

View File

@@ -11,18 +11,23 @@
template <typename T>
class ResultVal;
namespace CoreTiming {
struct EventType;
namespace Core {
class System;
}
namespace Core::Timing {
class CoreTiming;
struct EventType;
} // namespace Core::Timing
namespace Kernel {
class AddressArbiter;
class ClientPort;
class HandleTable;
class Process;
class ResourceLimit;
class Thread;
class Timer;
/// Represents a single instance of the kernel.
class KernelCore {
@@ -30,7 +35,14 @@ private:
using NamedPortTable = std::unordered_map<std::string, SharedPtr<ClientPort>>;
public:
KernelCore();
/// Constructs an instance of the kernel using the given System
/// instance as a context for any necessary system-related state,
/// such as threads, CPU core state, etc.
///
/// @post After execution of the constructor, the provided System
/// object *must* outlive the kernel instance itself.
///
explicit KernelCore(Core::System& system);
~KernelCore();
KernelCore(const KernelCore&) = delete;
@@ -51,9 +63,6 @@ public:
/// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table.
SharedPtr<Thread> RetrieveThreadFromWakeupCallbackHandleTable(Handle handle) const;
/// Retrieves a shared pointer to a Timer instance within the timer callback handle table.
SharedPtr<Timer> RetrieveTimerFromCallbackHandleTable(Handle handle) const;
/// Adds the given shared pointer to an internal list of active processes.
void AppendNewProcess(SharedPtr<Process> process);
@@ -66,6 +75,12 @@ public:
/// Retrieves a const pointer to the current process.
const Process* CurrentProcess() const;
/// Provides a reference to the kernel's address arbiter.
Kernel::AddressArbiter& AddressArbiter();
/// Provides a const reference to the kernel's address arbiter.
const Kernel::AddressArbiter& AddressArbiter() const;
/// Adds a port to the named port table
void AddNamedPort(std::string name, SharedPtr<ClientPort> port);
@@ -82,7 +97,6 @@ private:
friend class Object;
friend class Process;
friend class Thread;
friend class Timer;
/// Creates a new object ID, incrementing the internal object ID counter.
u32 CreateNewObjectID();
@@ -93,14 +107,8 @@ private:
/// Creates a new thread ID, incrementing the internal thread ID counter.
u64 CreateNewThreadID();
/// Creates a timer callback handle for the given timer.
ResultVal<Handle> CreateTimerCallbackHandle(const SharedPtr<Timer>& timer);
/// Retrieves the event type used for thread wakeup callbacks.
CoreTiming::EventType* ThreadWakeupCallbackEventType() const;
/// Retrieves the event type used for timer callbacks.
CoreTiming::EventType* TimerCallbackEventType() const;
Core::Timing::EventType* ThreadWakeupCallbackEventType() const;
/// Provides a reference to the thread wakeup callback handle table.
Kernel::HandleTable& ThreadWakeupCallbackHandleTable();

View File

@@ -16,7 +16,6 @@ bool Object::IsWaitable() const {
case HandleType::ReadableEvent:
case HandleType::Thread:
case HandleType::Process:
case HandleType::Timer:
case HandleType::ServerPort:
case HandleType::ServerSession:
return true;

View File

@@ -25,7 +25,6 @@ enum class HandleType : u32 {
Thread,
Process,
AddressArbiter,
Timer,
ResourceLimit,
ClientPort,
ServerPort,

View File

@@ -99,7 +99,13 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) {
vm_manager.Reset(metadata.GetAddressSpaceType());
const auto& caps = metadata.GetKernelCapabilities();
return capabilities.InitializeForUserProcess(caps.data(), caps.size(), vm_manager);
const auto capability_init_result =
capabilities.InitializeForUserProcess(caps.data(), caps.size(), vm_manager);
if (capability_init_result.IsError()) {
return capability_init_result;
}
return handle_table.SetSize(capabilities.GetHandleTableSize());
}
void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) {

View File

@@ -96,7 +96,7 @@ void ProcessCapabilities::InitializeForMetadatalessProcess() {
interrupt_capabilities.set();
// Allow using the maximum possible amount of handles
handle_table_size = static_cast<u32>(HandleTable::MAX_COUNT);
handle_table_size = static_cast<s32>(HandleTable::MAX_COUNT);
// Allow all debugging capabilities.
is_debuggable = true;
@@ -337,7 +337,7 @@ ResultCode ProcessCapabilities::HandleHandleTableFlags(u32 flags) {
return ERR_RESERVED_VALUE;
}
handle_table_size = (flags >> 16) & 0x3FF;
handle_table_size = static_cast<s32>((flags >> 16) & 0x3FF);
return RESULT_SUCCESS;
}

View File

@@ -156,7 +156,7 @@ public:
}
/// Gets the number of total allowable handles for the process' handle table.
u32 GetHandleTableSize() const {
s32 GetHandleTableSize() const {
return handle_table_size;
}
@@ -252,7 +252,7 @@ private:
u64 core_mask = 0;
u64 priority_mask = 0;
u32 handle_table_size = 0;
s32 handle_table_size = 0;
u32 kernel_version = 0;
ProgramType program_type = ProgramType::SysModule;

View File

@@ -44,8 +44,4 @@ ResultCode ReadableEvent::Reset() {
return RESULT_SUCCESS;
}
void ReadableEvent::WakeupAllWaitingThreads() {
WaitObject::WakeupAllWaitingThreads();
}
} // namespace Kernel

View File

@@ -39,8 +39,6 @@ public:
bool ShouldWait(Thread* thread) const override;
void Acquire(Thread* thread) override;
void WakeupAllWaitingThreads() override;
/// Unconditionally clears the readable event's state.
void Clear();

View File

@@ -19,7 +19,8 @@ namespace Kernel {
std::mutex Scheduler::scheduler_mutex;
Scheduler::Scheduler(Core::ARM_Interface& cpu_core) : cpu_core(cpu_core) {}
Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core)
: cpu_core{cpu_core}, system{system} {}
Scheduler::~Scheduler() {
for (auto& thread : thread_list) {
@@ -61,7 +62,7 @@ Thread* Scheduler::PopNextReadyThread() {
void Scheduler::SwitchContext(Thread* new_thread) {
Thread* const previous_thread = GetCurrentThread();
Process* const previous_process = Core::CurrentProcess();
Process* const previous_process = system.Kernel().CurrentProcess();
UpdateLastContextSwitchTime(previous_thread, previous_process);
@@ -94,8 +95,8 @@ void Scheduler::SwitchContext(Thread* new_thread) {
auto* const thread_owner_process = current_thread->GetOwnerProcess();
if (previous_process != thread_owner_process) {
Core::System::GetInstance().Kernel().MakeCurrentProcess(thread_owner_process);
SetCurrentPageTable(&Core::CurrentProcess()->VMManager().page_table);
system.Kernel().MakeCurrentProcess(thread_owner_process);
SetCurrentPageTable(&thread_owner_process->VMManager().page_table);
}
cpu_core.LoadContext(new_thread->GetContext());
@@ -111,7 +112,7 @@ void Scheduler::SwitchContext(Thread* new_thread) {
void Scheduler::UpdateLastContextSwitchTime(Thread* thread, Process* process) {
const u64 prev_switch_ticks = last_context_switch_time;
const u64 most_recent_switch_ticks = CoreTiming::GetTicks();
const u64 most_recent_switch_ticks = system.CoreTiming().GetTicks();
const u64 update_ticks = most_recent_switch_ticks - prev_switch_ticks;
if (thread != nullptr) {
@@ -223,8 +224,7 @@ void Scheduler::YieldWithLoadBalancing(Thread* thread) {
// Take the first non-nullptr one
for (unsigned cur_core = 0; cur_core < Core::NUM_CPU_CORES; ++cur_core) {
const auto res =
Core::System::GetInstance().CpuCore(cur_core).Scheduler().GetNextSuggestedThread(
core, priority);
system.CpuCore(cur_core).Scheduler().GetNextSuggestedThread(core, priority);
// If scheduler provides a suggested thread
if (res != nullptr) {

View File

@@ -13,7 +13,8 @@
namespace Core {
class ARM_Interface;
}
class System;
} // namespace Core
namespace Kernel {
@@ -21,7 +22,7 @@ class Process;
class Scheduler final {
public:
explicit Scheduler(Core::ARM_Interface& cpu_core);
explicit Scheduler(Core::System& system, Core::ARM_Interface& cpu_core);
~Scheduler();
/// Returns whether there are any threads that are ready to run.
@@ -162,6 +163,7 @@ private:
Core::ARM_Interface& cpu_core;
u64 last_context_switch_time = 0;
Core::System& system;
static std::mutex scheduler_mutex;
};

View File

@@ -26,6 +26,10 @@ ResultVal<SharedPtr<ServerSession>> ServerPort::Accept() {
return MakeResult(std::move(session));
}
void ServerPort::AppendPendingSession(SharedPtr<ServerSession> pending_session) {
pending_sessions.push_back(std::move(pending_session));
}
bool ServerPort::ShouldWait(Thread* thread) const {
// If there are no pending sessions, we wait until a new one is added.
return pending_sessions.empty();

View File

@@ -22,6 +22,8 @@ class SessionRequestHandler;
class ServerPort final : public WaitObject {
public:
using HLEHandler = std::shared_ptr<SessionRequestHandler>;
/**
* Creates a pair of ServerPort and an associated ClientPort.
*
@@ -51,22 +53,27 @@ public:
*/
ResultVal<SharedPtr<ServerSession>> Accept();
/// Whether or not this server port has an HLE handler available.
bool HasHLEHandler() const {
return hle_handler != nullptr;
}
/// Gets the HLE handler for this port.
HLEHandler GetHLEHandler() const {
return hle_handler;
}
/**
* Sets the HLE handler template for the port. ServerSessions crated by connecting to this port
* will inherit a reference to this handler.
*/
void SetHleHandler(std::shared_ptr<SessionRequestHandler> hle_handler_) {
void SetHleHandler(HLEHandler hle_handler_) {
hle_handler = std::move(hle_handler_);
}
std::string name; ///< Name of port (optional)
/// ServerSessions waiting to be accepted by the port
std::vector<SharedPtr<ServerSession>> pending_sessions;
/// This session's HLE request handler template (optional)
/// ServerSessions created from this port inherit a reference to this handler.
std::shared_ptr<SessionRequestHandler> hle_handler;
/// Appends a ServerSession to the collection of ServerSessions
/// waiting to be accepted by this port.
void AppendPendingSession(SharedPtr<ServerSession> pending_session);
bool ShouldWait(Thread* thread) const override;
void Acquire(Thread* thread) override;
@@ -74,6 +81,16 @@ public:
private:
explicit ServerPort(KernelCore& kernel);
~ServerPort() override;
/// ServerSessions waiting to be accepted by the port
std::vector<SharedPtr<ServerSession>> pending_sessions;
/// This session's HLE request handler template (optional)
/// ServerSessions created from this port inherit a reference to this handler.
HLEHandler hle_handler;
/// Name of the port (optional)
std::string name;
};
} // namespace Kernel

View File

@@ -63,42 +63,71 @@ void ServerSession::Acquire(Thread* thread) {
pending_requesting_threads.pop_back();
}
ResultCode ServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& context) {
auto* const domain_message_header = context.GetDomainMessageHeader();
if (domain_message_header) {
// Set domain handlers in HLE context, used for domain objects (IPC interfaces) as inputs
context.SetDomainRequestHandlers(domain_request_handlers);
// If there is a DomainMessageHeader, then this is CommandType "Request"
const u32 object_id{context.GetDomainMessageHeader()->object_id};
switch (domain_message_header->command) {
case IPC::DomainMessageHeader::CommandType::SendMessage:
if (object_id > domain_request_handlers.size()) {
LOG_CRITICAL(IPC,
"object_id {} is too big! This probably means a recent service call "
"to {} needed to return a new interface!",
object_id, name);
UNREACHABLE();
return RESULT_SUCCESS; // Ignore error if asserts are off
}
return domain_request_handlers[object_id - 1]->HandleSyncRequest(context);
case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: {
LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id);
domain_request_handlers[object_id - 1] = nullptr;
IPC::ResponseBuilder rb{context, 2};
rb.Push(RESULT_SUCCESS);
return RESULT_SUCCESS;
}
}
LOG_CRITICAL(IPC, "Unknown domain command={}",
static_cast<int>(domain_message_header->command.Value()));
ASSERT(false);
void ServerSession::ClientDisconnected() {
// We keep a shared pointer to the hle handler to keep it alive throughout
// the call to ClientDisconnected, as ClientDisconnected invalidates the
// hle_handler member itself during the course of the function executing.
std::shared_ptr<SessionRequestHandler> handler = hle_handler;
if (handler) {
// Note that after this returns, this server session's hle_handler is
// invalidated (set to null).
handler->ClientDisconnected(this);
}
// TODO(Subv): Force a wake up of all the ServerSession's waiting threads and set
// their WaitSynchronization result to 0xC920181A.
// Clean up the list of client threads with pending requests, they are unneeded now that the
// client endpoint is closed.
pending_requesting_threads.clear();
currently_handling = nullptr;
}
void ServerSession::AppendDomainRequestHandler(std::shared_ptr<SessionRequestHandler> handler) {
domain_request_handlers.push_back(std::move(handler));
}
std::size_t ServerSession::NumDomainRequestHandlers() const {
return domain_request_handlers.size();
}
ResultCode ServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& context) {
if (!context.HasDomainMessageHeader()) {
return RESULT_SUCCESS;
}
// Set domain handlers in HLE context, used for domain objects (IPC interfaces) as inputs
context.SetDomainRequestHandlers(domain_request_handlers);
// If there is a DomainMessageHeader, then this is CommandType "Request"
const auto& domain_message_header = context.GetDomainMessageHeader();
const u32 object_id{domain_message_header.object_id};
switch (domain_message_header.command) {
case IPC::DomainMessageHeader::CommandType::SendMessage:
if (object_id > domain_request_handlers.size()) {
LOG_CRITICAL(IPC,
"object_id {} is too big! This probably means a recent service call "
"to {} needed to return a new interface!",
object_id, name);
UNREACHABLE();
return RESULT_SUCCESS; // Ignore error if asserts are off
}
return domain_request_handlers[object_id - 1]->HandleSyncRequest(context);
case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: {
LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id);
domain_request_handlers[object_id - 1] = nullptr;
IPC::ResponseBuilder rb{context, 2};
rb.Push(RESULT_SUCCESS);
return RESULT_SUCCESS;
}
}
LOG_CRITICAL(IPC, "Unknown domain command={}",
static_cast<int>(domain_message_header.command.Value()));
ASSERT(false);
return RESULT_SUCCESS;
}

View File

@@ -46,6 +46,14 @@ public:
return HANDLE_TYPE;
}
Session* GetParent() {
return parent.get();
}
const Session* GetParent() const {
return parent.get();
}
using SessionPair = std::tuple<SharedPtr<ServerSession>, SharedPtr<ClientSession>>;
/**
@@ -78,23 +86,16 @@ public:
void Acquire(Thread* thread) override;
std::string name; ///< The name of this session (optional)
std::shared_ptr<Session> parent; ///< The parent session, which links to the client endpoint.
std::shared_ptr<SessionRequestHandler>
hle_handler; ///< This session's HLE request handler (applicable when not a domain)
/// Called when a client disconnection occurs.
void ClientDisconnected();
/// This is the list of domain request handlers (after conversion to a domain)
std::vector<std::shared_ptr<SessionRequestHandler>> domain_request_handlers;
/// Adds a new domain request handler to the collection of request handlers within
/// this ServerSession instance.
void AppendDomainRequestHandler(std::shared_ptr<SessionRequestHandler> handler);
/// List of threads that are pending a response after a sync request. This list is processed in
/// a LIFO manner, thus, the last request will be dispatched first.
/// TODO(Subv): Verify if this is indeed processed in LIFO using a hardware test.
std::vector<SharedPtr<Thread>> pending_requesting_threads;
/// Thread whose request is currently being handled. A request is considered "handled" when a
/// response is sent via svcReplyAndReceive.
/// TODO(Subv): Find a better name for this.
SharedPtr<Thread> currently_handling;
/// Retrieves the total number of domain request handlers that have been
/// appended to this ServerSession instance.
std::size_t NumDomainRequestHandlers() const;
/// Returns true if the session has been converted to a domain, otherwise False
bool IsDomain() const {
@@ -129,8 +130,30 @@ private:
/// object handle.
ResultCode HandleDomainSyncRequest(Kernel::HLERequestContext& context);
/// The parent session, which links to the client endpoint.
std::shared_ptr<Session> parent;
/// This session's HLE request handler (applicable when not a domain)
std::shared_ptr<SessionRequestHandler> hle_handler;
/// This is the list of domain request handlers (after conversion to a domain)
std::vector<std::shared_ptr<SessionRequestHandler>> domain_request_handlers;
/// List of threads that are pending a response after a sync request. This list is processed in
/// a LIFO manner, thus, the last request will be dispatched first.
/// TODO(Subv): Verify if this is indeed processed in LIFO using a hardware test.
std::vector<SharedPtr<Thread>> pending_requesting_threads;
/// Thread whose request is currently being handled. A request is considered "handled" when a
/// response is sent via svcReplyAndReceive.
/// TODO(Subv): Find a better name for this.
SharedPtr<Thread> currently_handling;
/// When set to True, converts the session to a domain at the end of the command
bool convert_to_domain{};
/// The name of this session (optional)
std::string name;
};
} // namespace Kernel

View File

@@ -6,7 +6,6 @@
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/shared_memory.h"
@@ -34,8 +33,8 @@ SharedPtr<SharedMemory> SharedMemory::Create(KernelCore& kernel, Process* owner_
shared_memory->backing_block_offset = 0;
// Refresh the address mappings for the current process.
if (Core::CurrentProcess() != nullptr) {
Core::CurrentProcess()->VMManager().RefreshMemoryBlockMappings(
if (kernel.CurrentProcess() != nullptr) {
kernel.CurrentProcess()->VMManager().RefreshMemoryBlockMappings(
shared_memory->backing_block.get());
}
} else {

View File

@@ -20,6 +20,7 @@
#include "core/hle/kernel/address_arbiter.h"
#include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/client_session.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/mutex.h"
@@ -47,23 +48,6 @@ constexpr bool IsValidAddressRange(VAddr address, u64 size) {
return address + size > address;
}
// Checks if a given address range lies within a larger address range.
constexpr bool IsInsideAddressRange(VAddr address, u64 size, VAddr address_range_begin,
VAddr address_range_end) {
const VAddr end_address = address + size - 1;
return address_range_begin <= address && end_address <= address_range_end - 1;
}
bool IsInsideAddressSpace(const VMManager& vm, VAddr address, u64 size) {
return IsInsideAddressRange(address, size, vm.GetAddressSpaceBaseAddress(),
vm.GetAddressSpaceEndAddress());
}
bool IsInsideNewMapRegion(const VMManager& vm, VAddr address, u64 size) {
return IsInsideAddressRange(address, size, vm.GetNewMapRegionBaseAddress(),
vm.GetNewMapRegionEndAddress());
}
// 8 GiB
constexpr u64 MAIN_MEMORY_SIZE = 0x200000000;
@@ -105,14 +89,14 @@ ResultCode MapUnmapMemorySanityChecks(const VMManager& vm_manager, VAddr dst_add
return ERR_INVALID_ADDRESS_STATE;
}
if (!IsInsideAddressSpace(vm_manager, src_addr, size)) {
if (!vm_manager.IsWithinAddressSpace(src_addr, size)) {
LOG_ERROR(Kernel_SVC,
"Source is not within the address space, addr=0x{:016X}, size=0x{:016X}",
src_addr, size);
return ERR_INVALID_ADDRESS_STATE;
}
if (!IsInsideNewMapRegion(vm_manager, dst_addr, size)) {
if (!vm_manager.IsWithinNewMapRegion(dst_addr, size)) {
LOG_ERROR(Kernel_SVC,
"Destination is not within the new map region, addr=0x{:016X}, size=0x{:016X}",
dst_addr, size);
@@ -238,7 +222,7 @@ static ResultCode SetMemoryPermission(VAddr addr, u64 size, u32 prot) {
auto* const current_process = Core::CurrentProcess();
auto& vm_manager = current_process->VMManager();
if (!IsInsideAddressSpace(vm_manager, addr, size)) {
if (!vm_manager.IsWithinAddressSpace(addr, size)) {
LOG_ERROR(Kernel_SVC,
"Source is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr,
size);
@@ -299,7 +283,7 @@ static ResultCode SetMemoryAttribute(VAddr address, u64 size, u32 mask, u32 attr
}
auto& vm_manager = Core::CurrentProcess()->VMManager();
if (!IsInsideAddressSpace(vm_manager, address, size)) {
if (!vm_manager.IsWithinAddressSpace(address, size)) {
LOG_ERROR(Kernel_SVC,
"Given address (0x{:016X}) is outside the bounds of the address space.", address);
return ERR_INVALID_ADDRESS_STATE;
@@ -597,6 +581,7 @@ enum class BreakType : u32 {
PostNROLoad = 4,
PreNROUnload = 5,
PostNROUnload = 6,
CppException = 7,
};
struct BreakReason {
@@ -669,6 +654,9 @@ static void Break(u32 reason, u64 info1, u64 info2) {
"Signalling debugger, Unloaded an NRO at 0x{:016X} with size 0x{:016X}", info1,
info2);
break;
case BreakType::CppException:
LOG_CRITICAL(Debug_Emulated, "Signalling debugger. Uncaught C++ exception encountered.");
break;
default:
LOG_WARNING(
Debug_Emulated,
@@ -914,6 +902,7 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
}
const auto& system = Core::System::GetInstance();
const auto& core_timing = system.CoreTiming();
const auto& scheduler = system.CurrentScheduler();
const auto* const current_thread = scheduler.GetCurrentThread();
const bool same_thread = current_thread == thread;
@@ -923,9 +912,9 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
if (same_thread && info_sub_id == 0xFFFFFFFFFFFFFFFF) {
const u64 thread_ticks = current_thread->GetTotalCPUTimeTicks();
out_ticks = thread_ticks + (CoreTiming::GetTicks() - prev_ctx_ticks);
out_ticks = thread_ticks + (core_timing.GetTicks() - prev_ctx_ticks);
} else if (same_thread && info_sub_id == system.CurrentCoreIndex()) {
out_ticks = CoreTiming::GetTicks() - prev_ctx_ticks;
out_ticks = core_timing.GetTicks() - prev_ctx_ticks;
}
*result = out_ticks;
@@ -1490,13 +1479,14 @@ static ResultCode WaitForAddress(VAddr address, u32 type, s32 value, s64 timeout
return ERR_INVALID_ADDRESS;
}
auto& address_arbiter = Core::System::GetInstance().Kernel().AddressArbiter();
switch (static_cast<AddressArbiter::ArbitrationType>(type)) {
case AddressArbiter::ArbitrationType::WaitIfLessThan:
return AddressArbiter::WaitForAddressIfLessThan(address, value, timeout, false);
return address_arbiter.WaitForAddressIfLessThan(address, value, timeout, false);
case AddressArbiter::ArbitrationType::DecrementAndWaitIfLessThan:
return AddressArbiter::WaitForAddressIfLessThan(address, value, timeout, true);
return address_arbiter.WaitForAddressIfLessThan(address, value, timeout, true);
case AddressArbiter::ArbitrationType::WaitIfEqual:
return AddressArbiter::WaitForAddressIfEqual(address, value, timeout);
return address_arbiter.WaitForAddressIfEqual(address, value, timeout);
default:
LOG_ERROR(Kernel_SVC,
"Invalid arbitration type, expected WaitIfLessThan, DecrementAndWaitIfLessThan "
@@ -1521,13 +1511,14 @@ static ResultCode SignalToAddress(VAddr address, u32 type, s32 value, s32 num_to
return ERR_INVALID_ADDRESS;
}
auto& address_arbiter = Core::System::GetInstance().Kernel().AddressArbiter();
switch (static_cast<AddressArbiter::SignalType>(type)) {
case AddressArbiter::SignalType::Signal:
return AddressArbiter::SignalToAddress(address, num_to_wake);
return address_arbiter.SignalToAddress(address, num_to_wake);
case AddressArbiter::SignalType::IncrementAndSignalIfEqual:
return AddressArbiter::IncrementAndSignalToAddressIfEqual(address, value, num_to_wake);
return address_arbiter.IncrementAndSignalToAddressIfEqual(address, value, num_to_wake);
case AddressArbiter::SignalType::ModifyByWaitingCountAndSignalIfEqual:
return AddressArbiter::ModifyByWaitingCountAndSignalToAddressIfEqual(address, value,
return address_arbiter.ModifyByWaitingCountAndSignalToAddressIfEqual(address, value,
num_to_wake);
default:
LOG_ERROR(Kernel_SVC,
@@ -1542,10 +1533,11 @@ static ResultCode SignalToAddress(VAddr address, u32 type, s32 value, s32 num_to
static u64 GetSystemTick() {
LOG_TRACE(Kernel_SVC, "called");
const u64 result{CoreTiming::GetTicks()};
auto& core_timing = Core::System::GetInstance().CoreTiming();
const u64 result{core_timing.GetTicks()};
// Advance time to defeat dumb games that busy-wait for the frame to end.
CoreTiming::AddTicks(400);
core_timing.AddTicks(400);
return result;
}

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