The Host1x block of the TX1 supports 14 separate channels to which commands can be issued, these all run asynchronously so are emulated the same way as GPU channels with one FIFO emulation thread each. The command FIFO itself is very similar to the GPFIFO found in the GPU however there are some differences, mainly the introduction of classes (similar to engines) and the Mask opcode (which allows writing to a specific set of offsets much more efficiently).
There is an internal Host1x class which functions similar to the GPFIFO class in the GPU, handling general operations such as syncpoint waits, this is accessed via the simple method interface. Other channels such as NVDEC and VIC are behind the 'Tegra Host Interface' (THI) in HW, this abstracts out the classes internal details and provides a uniform method interface ontop of the Host1x method one. We emulate the THI as a templated wrapper for the underlying class.
Syncpoint increments in Host1x are different to GPU, the THI allows submitting increment requests that will be queued up and only be applied after a specific condition in the associated engine is met; however the option to for immediate increments is also available.
This avoids the excessive repetition needed for the case where array
members have no default constructor.
eg:
```c++
std::array<Type, 10> channels{util::MakeFilledArray<Type, 10>(typeConstructorArg, <...>)};
```
nvmap allows mapping handles into the SMMU address space through 'pins'. These are refcounted mappings that are lazily freed when required due to AS space running out. Nvidia implements this by using several MRU lists of handles in order to choose which ones to free and which ones to keep, however as we are unlikely to even run into the case of not having enough address space a naive queue approach works fine. This pin infrastructure is used by nvdrv's host1x channel implementation in order to handle mapping of both command and data buffers for submit.
host1x channels are generally similar to GPU channels however there is only one channel for each specific class (like a GPU engine) and an address space is shared between them all.
This PR implements the simple IOCTLs with the larger ones that will depend on changes outside of nvdrv being left for future commits. This is enough to partly run oss-nvjpeg.
The element containing the size first needs to be saved to a save slot with Save<T, slotId>, it can then be read back later as the size of a span with SlotSizeSpan<T, slotId>. This is needed to support the Host1XChannel Submit IOCTL.
Maxwell3D registers were primarily written with absolute offsets and ended up being fairly messy due to attempting to emulate this using struct relative positioning resulting in a lot of pointless padding members. This has now been improved by utilizing `OffsetMember` to directly use offsets resulting in much neater code.
It was found to be semantically advantageous to directly pass-through certain operators such as the assignment (`=`) and array index (`[]`) operators. These would require a dereference prior to their usage otherwise but now can be directly used.
The offset of a member in a structure was determined by its relative position and compiler alignment. This is unoptimal for larger structures such as those found in GPU Engines that are primarily named by offset rather than relative positioning and end up requiring a massive amount of padding to function as is. A solution to this problem was simply to supply member offsets directly which can be done by using `OffsetMember` alongside a `union`.
We used to manually call JNI UTF-8 string allocation and deallocation functions when utilizing a `jstring` but this could be erroneous and is just inconvenient. All of this has now been consolidated into an class `JniString` which is a wrapper around `std::string` and creates a copy of the contents of the `jstring` in its constructor and passes them into the `std::string` constructor.
The Vulkan Pipeline Barriers were unoptimal and incorrect to some degree prior as we purely synchronized images and not staging buffers. This has now been fixed and improved in general with more relevant synchronization.
`EmulationActivity.vibrateDevice` would assert when a `null` Vibrator is provided due to one not being set in the controller configuration. This has now been fixed by the code not playing a vibration when a vibration device isn't selected.
The guest -> host vibration conversion code was entirely broken as it didn't set the vibration `start`/`end` timestamps correctly for a cycle nor did it subtract from the `totalAmplitude` (`currentAmplitude` now) when it a cycle ended due to an incorrect `if` statement and contents. It would just end up saturating the amplitude as much as possible by adding more and more to `totalAmplitude` on every cycle while never subtracting which is entirely wrong and led to a very noticeable drop in amplitude when a vibration was repeated.
It's been entirely reworked to fix all the issues listed above and remove a lot of code that had no understandable purpose. More comments have also been added to the code to make it more readable with better variable and function naming alongside it.
Submodules were named as their relative paths prior which were not very readable, this has now been replaced with proper titles that correspond to the submodule.
To offset some of the performance overhead of using debug builds, we now optimize all libraries using `-Ofast` while building Skyline itself with `-O0`.
The version of libcxx shipped with Android NDK is fairly outdated and doesn't contain several features we desire such as C++ 20 ranges. This has been fixed by using libcxx directly from the LLVM Project which has been added as a submodule and can be updated independently of NDK.
We've moved to using a beta AGP as `7.0.2` is breaks `clangd` and other C++ features on Beta/Canary Android Studio. NDK was additionally updated with `mbedtls` to fix warnings caused by it alongside some other minor fixes to code for newer versions of libcxx.
The new AGP has a bug where it does not look for executables specified in `android_gradle_build.json` in `PATH` that includes `ninja` which is provided by the `ninja-build` package on the system rather than Android SDK's CMake on GitHub Actions (Ubuntu 20.04). This has been fixed by symlinking `/usr/bin/ninja` to the project root which is searched in for the `ninja` executable.
Locking `KProcess::threadMutex` when a process is being killed by another thread with `join` can lead to the non-joining killer effectively joining as it's waiting on the joining killer to relinquish the mutex. This has been fixed by having an atomic boolean tracking if the process has already been killed and if it has, immediately returning prior to locking the mutex for any non-joining killers.
Resampling would sometimes perform an OOB read into `inputBuffer` due it not containing enough data to calculate corresponding the output sample, this has been fixed by introducing bounds checking to ensure that the buffer has enough data.
The method used to finish (`finishAndRemoveTask`) an activity prior to going back to `MainActivity` or restarting the process led to the process prematurely exiting entirely and would result in it not being restarted or another activity not being launched. This has now been fixed by utilizing `finishAffinity` in its place which correctly only ends the activities with the same affinity as the caller.
Members of `GuestTexture` were apparently not being initialized and this led to UB since they would be read as random values. Titles such as Super Mario Odyssey avoided setting `baseArrayLayer` which led to it being left at the default value which was completely random and this would lead to crashes. This commit fixes this by initializing said values correctly.
Some titles don't clear the output buffer prior to submission, as the service is expected to fill all of it in, our audren implementation is incomplete and doesn't end up doing this leaving the contents of the buffer to be undefined leading to UB in the form of SEGFAULTs or the application throwing a fatal error. This has been patched over by 0-filling the buffer which is a sane default value for the fields that aren't filled in albeit not a replacement for a proper audren implementation.
Certain titles can submit logs where the last field is one off by the buffer end, the logger loop now considers this and terminates if there isn't enough data left to read the field type and length.
Access to the `vibrations` field in `vibrations[3].period` could lead to UB, this has been replaced with a proper check which adds up the period over all vibrations instead. A minor cleanup with variable names and explicit types for integer arithmetic has also been done.
If a non-builtin vibrator was attempted to be fetched, it'd insert it in the vibrator cache and return directly as opposed to playing the vibration on it prior to returning. This has now been fixed, the value is both put into the cache and the vibration is played on it.
The decomposition from `texture::Dimension` to `vk::Rect2D` was somehow implicit and completely incorrect resulting in wrong conversion with undefined values. It's now been fixed by explicitly setting `vk::Rect2D::extent` to `scissor` specifically.
The second parameter of `std::string_view::substr` was assumed to be an end position (similar to `std::span`) rather than `count` which it is. As a result of this, it was entirely broken but only held together by a constant factor being subtracted from it which was derived by trial and error. It's now been fixed by returning a count rather than the absolute position.
Library headers would produce errors that are out of our control and as a result of that, we just want to ignore this. This is possible by including the offending headers as system headers, compilers don't emit any warnings arising from them. This was extended to all libraries rather than just those which currently emitted warnings for consistency's sake.
Fix a bug where attempting to launch Skyline from the launcher while emulation was in progress would result in `MainActivity` launching rather than `EmulationActivity`. We always want `EmulationActivity` to stay on top of the stack and be launched whenever Skyline is resumed, no other activity should be able to run in parallel to `EmulationActivity` in any user-accessible manner.
Git became significantly slower for nearly all actions due to the inclusion of Boost as a submodule which in turn had an extremely large amount of submodules itself for every single Boost component, this especially effected clients like GitKraken which had multi-second delays in operations and became unusable due to it. The reason for this ended up being checking for modifications in the Boost submodule which has been disabled by using [`submodule.<name>.ignore`](https://git-scm.com/docs/git-config#Documentation/git-config.txt-submoduleltnamegtignore) which disables any checks on the Boost submodule for changes and fixes the prior performance degradation.