Implements the entirety of Maxwell3D Depth/Stencil state for both faces including compare/write masks and reference value. Maxwell3D register `stencilTwoSideEnable` is ignored as its behavior is unknown and could mean the same behavior for both stencils or the back facing stencil being disabled as a result of this it is unimplemented.
We don't respect the host subresource layout in synchronizing linear textures from the guest to the host when mapped to memory directly, this leads to texture corruption and while the real fix would involve respecting the host subresource layout, this has been deferred for later as real world performance advantages/disadvantages associated with this change can be observed more carefully to determine if it's worth it.
Color RTs are disabled by setting their format as `None`, it was removed while transitioning to macros and resulted in a missing format exception. It has been readded as several applications depend on this behavior.
Using `std::vector` for shader bytecode led to a lot of reallocation due to constant resizing, switching over the static vector allows for a single static allocation of the maximum possible guest shader size (1 MiB) to be done for every stage resulting in a 6 MiB preallocation which is unnoticeable given the total memory overhead of running a Switch application.
The `OneMinusSourceAlpha` blending factor was converted to `eOneMinusSrcColor` rather than `eOneMinusSrcAlpha` leading to incorrect blending behavior in certain titles. A similar issue with the order of `MinimumGL`/`MaximumGL` and `SubtractGL`/`ReverseSubtractGL` being the opposite of what it should've been, both of these issues have been fixed.
`NextSubpassNode` didn't increment `subpassIndex` which runs commands with the wrong subpass index resulting in them accessing invalid attachments or other bugs that may arise from using the wrong subpass.
All Maxwell3D state was passed by reference to the draw command lambda, this would break if there was more than one pass or the state was changed in any way before execution. All state has now been serialized by value into the draw command lambda capture, retaining state regardless of mutations of the class state.
Any usage of a resource in a command now requires attaching that resource externally and will not be implicitly attached on usage, this makes attaching of resources consistent and allows for more lax locking requirements on resources as they can be locked while attaching and don't need to be for any commands, it also avoids redundantly attaching a resource in certain cases.
If an object is attached to a `FenceCycle` twice then it would cause `FenceCycleDependency::next` to be overwritten and lead to destruction of dependencies prior to the fence being signaled causing usage of deleted resources. This commit fixes this by tracking what fence cycle a dependency is currently attached to and doesn't reattach if it's already attached to the current fence cycle.
An assumption was hardcoded into `Shader::Profile` regarding devices supporting demotion of shader invocations to helpers. This assumption wasn't backed by enabling the `VK_EXT_shader_demote_to_helper_invocation` extension via a quirk leading to assertions when it was used by the shader compiler, a quirk has now been added for the extension and is supplied to the shader compiler accordingly.
If the controller type was changed from a type with a larger amount of buttons/axes to one with a fewer amount, a crash would occur due to the transition animation retaining those elements as children yet returning `NO_POSITION` from `getChildAdapterPosition` in `DividerItemDecoration` which was an unhandled case and led to an OOB array access.
A bug caused by not passing the index argument to `ControllerActivity` led to all preferences opening the activity that pertained to Controller #1. This was fixed by passing the `index` argument in the activity launch intent.
Fixes texture corruption due to incorrect synchronization, the barrier would not enforce waiting till the texture was entirely rendered causing an incomplete texture to be downloaded which lead to rendering bugs for certain GPUs including ARM's Mali GPUs.
A bug caused an assertion if both `VK_EXT_custom_border_color` and `VK_EXT_vertex_attribute_divisor` due to mistakenly unlinking `PhysicalDeviceVertexAttributeDivisorFeaturesEXT` instead of `PhysicalDeviceCustomBorderColorFeaturesEXT` when `VK_EXT_custom_border_color` isn't supported which would potentially lead to unlinking the same structure twice and cause the assertion.
Implements inline constant buffer updates that are written to the CPU copy of the buffer rather than generating an actual inline buffer write, this works for TIC/TSC index updates but won't work when the buffer is expected to actually be updated inline with regard to sequence rather than just as a buffer upload prior to rendering.
GPU-sided constant buffer updates will be implemented later with optimizations for updating an entire range by handling GPFIFO `Inc`/`NonInc`directly and submitting it as a host inline buffer update.
There should only ever be a single instance of a `ActiveDescriptorSet` that tracks the lifetime of a descriptor set as the destructor is responsible for freeing the descriptor set.
There are cases where a new object inheriting the descriptor set needs to be created in these cases we need to have move semantics and make the destructor of the prior object inert, this allows for moving to the new object without any side effects. If the copy constructor was used in these cases the older object would free the set on its destruction which would lead to the set being invalid on existing instances which is incorrect behavior and would likely lead to driver crashes.
The descriptor sets should now contain a combined image and sampler handle for any sampled textures in the guest shader from the supplied offset into the texture constant buffer.
Note: Games tend to rely on inline constant buffer updates for writing the texture constant buffer and due to it not being implemented, the value will be read as 0 which is incorrect.
We want read semantics inside the constant buffer object via the mappings to avoid a pointless GPU VMM mapping lookup. It is a fairly frequent operation so this is necessary, the ability to write directly will be added in the future as well.
Implements parsing for the Maxwell 3D TIC pool and conversion of a TIC into a `GuestTexture`, support is limited to pitch-linear RGB565/A8R8G8B8 textures at the moment but will be extended as games utilize more formats and layouts. Support for 1D buffers is also omitted at the moment since they need special handling with them effectively being treated as buffers in Vulkan rather than images.
The pitch of the texture should always be supplied in terms of bytes as it denotes alignment on a byte boundary rather than a pixel one, it is also always utilized in terms of bytes rather than pixels so this avoids an unnecessary conversion.
Note: GBP stride unit was assumed to be pixels earlier but is likely bytes which is why there are no changes to the supplied value there, if this is not the case it'll be fixed in the future
Maxwell3D `TextureSamplerControl` (TSC) are fully converted into Vulkan samplers with extension backing for all aspects that require them (border color/reduction mode) and approximations where Vulkan doesn't support certain functionality (sampler address mode) alongside cases where extensions may not be present (border color).
Code involving caching of mappings was copied from `RenderTarget` without much consideration for applicability in buffers, the reason for caching mappings in RTs was that the view may be invalidated by more than the IOVA/Size being changed but this doesn't hold true for buffers generally so invalidation can only be on the view level with the mappings being looked up every time since the invalidation would likely change them.
`std::hash` doesn't have a generic template where it can be utilized for arbitrary trivial objects and implementing this might result in conflicts with other types. To fix this a generic templated hash is now provided as a utility structure, that can be utilized directly in hash-based containers such as `unordered_map`.
Nullability allow for optional semantics where a span may be explicitly invalidated with `nullptr` being used as a sentinel value for it and a boolean operator that allows trivial checking for if the span is valid or not.
Adds support for index buffers including U8 index buffers via the `VK_EXT_index_type_uint8` extension which has been added as an optional quirk but an exception will be thrown if the guest utilizes it but the host doesn't support it.
Add support for parsing and combining `VertexA` and `VertexB` programs into a single vertex pipeline program prior to compilation, atomic reparsing and combining is supported to only reparse the stage that was modified and recombine once at most within a single pipeline compilation.
Atomically invalidate pipeline stages as runtime information that pertains to them changes rather than never recompiling pipelines on runtime information being updated resulting in out of date pipelines or recompiling all pipelines on any runtime information updates.
Shader compilation is now broken into shader program parsing and pipeline shader compilation which will allow for supporting dual vertex shaders and more atomic invalidation depending on runtime state limiting the amount of work that is redone.
Bindings are now properly handled allowing for bound UBOs to be converted to the appropriate host UBO as designated by the shader compiler by creating Vulkan Descriptor Sets that match it.
We need this to make the distinction between a shader and pipeline stage in as shader programs are bound at a different rate than that of pipeline stage resources such as UBO.
An instance of `Shader::Backend::Bindings` must be retained across all stages for correct emission of bindings, which is now done inside `GraphicsContext::GetShaderStages`.
The vertex attribute types supplied prior were just the default which is `Float`, this works for some cases but will entirely break if the attribute type isn't a float. The attribute types are now set correctly.
Only copying a single aspect was supported by `CopyIntoStagingBuffer` earlier due to not supplying a `VkBufferImageCopy` for each aspect separately, this has now been done with Color/Depth/Stencil aspects having their own `VkBufferImageCopy` for the `VkCmdCopyImageToBuffer` command.
The definition of the `TextureView` class was spread across `texture.cpp` and has now been moved to the top of the file above the other half of the definition.
A buffer with 0 as the start/end IOVA should be invalid as there shouldn't be any mappings at 0 in GPU VA, titles such as Puyo Puyo Tetris configure the Vertex Buffer with 0 IOVAs which leads to a segmentation fault without this exception.
The lifetime of a texture and buffer view is now bound by the `FenceCycle` in `CommandExecutor`, this ensures that a `VkImageView` isn't destroyed prior to usage leading to UB.
The lifetime of all textures bound to a RenderPass alongside syncing of textures is already handled by `CommandExecutor` and doesn't need to be redundantly handled by `RenderPassNode`. It's been removed as a result of this.
Adds the depth/stencil RT as an attachment for the draw but with `VkPipelineDepthStencilStateCreateInfo` stubbed out, it'll not function correctly and the contents will not be what the guest expects them to be.
Support for clearing the depth/stencil RT has been added as its own function via either optimized `VkAttachmentLoadOp`-based clears or `vkCmdClearAttachments`. A bit of cleanup has also been done for color RT clears with the lambda for the slow-path purely calling the command rather than creating the parameter structures.
Implements `AddClearDepthStencilSubpass` in `CommandExecutor` which is similar to `ClearColorAttachment` in that it uses `VK_ATTACHMENT_LOAD_OP_CLEAR` for the clear which is far more efficient than using `VK_ATTACHMENT_LOAD_OP_LOAD` then doing the clear.
The stage/access mask for `VkSubpassDependency` were hardcoded to only be valid for color attachments earlier, this has now been fixed by branching based on the format aspect.
Sets `VkImageUsageFlags` correctly rather than hardcoding it for color attachments and adds multiple `VkBufferImageCopy` to `VkCmdCopyBufferToImage` for Color/Depth/Stencil aspects of an image.
Support the Maxwell3D Depth RT for Z-buffering, this just creates an equivalent `RenderTarget` object with no support on the API-user side (IE: `Draw` and `ClearBuffers`).
This prefixes all RT functions that deal with color RTs with `Color` and abstracts out common functions that will be used for both color and depth RTs. All common Maxwell3D structures are also moved out of the `ColorRenderTarget` (`RenderTarget` previously) structure.
To allow for caching of pipelines on the host a `VkPipelineCache` has been added, it is entirely in-memory and is not flushed to the disk which'll be done in the future alongside caching guest shaders to further avoid translation where possible.
Uses all Maxwell3D state converted into Vulkan state to do an equivalent draw on the host GPU, it sets up RT/Vertex Buffer/Vertex Attribute/Shader state and creates a stubbed out `VkPipelineLayout` for the draw. Any descriptor state isn't currently handled and is yet to be implemented, currently there's no Vulkan pipeline cache supplied which will be implemented subsequently.
We require a handle to the current renderpass and the index of the subpass in certain cases, this is now tracked by the `CommandExecutor` and passed in as a parameter to `NextSubpassFunctionNode` and the newly-introduced `SubpassFunctionNode`.
Switch from `SubmitWithCycle` to manually allocating the active command buffer to tag dependencies with the `FenceCycle` that prevents them from being mutated prior to execution. This new paradigm could also allow eager recording of commands with only submission being deferred.
`CommandScheduler` API users can now directly allocate an active command buffer that they need to manage alongside its fence, this can allow for more efficient recording as it doesn't need to be immediately submitted after, it can also allow attaching objects to a `FenceCycle` prior to submission that can be useful for locking resources.
Compiles shaders supplied by the guest with caching and automatic invalidation, the size of the shader is also automatically determined by looking for `BRA $` instructions which cause an infloop, it should be noted that we have a maximum shader bytecode size, any shader above this size will not be supported.
Graphics shaders can now be compiled using the shader compiler and emit SPIR-V that can be used on the host. The binding state isn't currently handled alongside constant buffers and textures support in `GraphicsEnvironment` yet.
The operands of the subtraction in the X/Y translation calculation were the wrong way around which led to negative translations that would translate the viewport off the screen.
The default color write mask should mask no channels and write all of them and should be mutated to mask out certain channels as required by the guest.
We cannot statically construct the vertex buffer/attribute arrays for Vulkan due to inactive attributes or buffers which isn't possible on Vulkan, we also cannot just change the count dynamically as there might be disabled buffers or attributes in the middle. We just have a `static_array` which should dynamically be filled in with buffer binding/attribute Vulkan structures before submission.
Buffers generally don't have formats that are fundamentally associated with them unless they're texel buffers, if that is the case it can be manually set in `BufferView`.
The Buffer Manager handles mapping of guest buffers to host buffer views with automatic handling of sub-buffers and eventually supporting recreation of overlapping buffers to create a single larger buffer.
Implements infrastructure for using guest buffers on the host for rendering, a `BufferManager` is still missing which'd handle mapping from guest buffers to host buffers and will be subsequently committed. It should be noted that `BufferView` is also disconnected from `Buffer` and shared for every instance with the same properties like `TextureView` is now.
We want `TextureView`(s) to be disconnected from the backing on the host and instead represent a specific texture on the guest with a backing that can change depending on mapping of new textures which'd invalidate the backing but should now be automatically repointed to an appropriate new backing. This approach also requires locking of the backing to function as it is mutable till it has been locked or the backing has an attached `FenceCycle` that hasn't been signaled which will be added for `CommandExecutor` in a subsequent commit.
Introduces the `supportsShaderViewportIndexLayer` quirk and sets `Shader::Profile::support_int64_atomics` depending on if the `supportsAtomicInt64` quirk is available.
Introduces the `floatControls`, `supportsSubgroupVote` and `subgroupSize` quirks for the shader compiler which are based on Vulkan `PhysicalDevice` properties.
Vulkan has officially deprecated `VK_VERSION_*` macros for versioning as it has introduced the variant into the version. It should however be `0` for the Vulkan APi and doesn't need to be printed.
Introduces several quirks for optional features used by the shader compiler which are now reported in the `Shader::HostTranslateInfo` and `Shader::Profile` structure. There are still property-related quirks for the shader compiler which haven't been implemented in this commit.
A `Buffer` class was created to hold any generic Vulkan buffer object with `span` semantics, `StagingBuffer` was implemented atop it as a wrapper for `Buffer` that inherits from `FenceCycleDependency` and can be used as such.
It was determined that `backing` wasn't a very descriptive name and that it conflicted with the texture's own backing, the name was changed to `texture` to make it more apparent that it was specifically the `Texture` object backing the view.
A memory manager function to read into a vector till it satisfies the supplied function or hits an early stop condition like hitting the end of vector or reaching an unmapped region. This can be used to efficiently scan for values in GPU VA.
When `VK_EXT_vertex_attribute_divisor` is not available, `VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT` is unlinked from the device enabled feature list as it is undefined behavior to link a structure provided by an extension without enabling that extension.
`EXT_SET_V` would enable the extension regardless of if it was actually the correct extension or if the version was high enough as long as the hash matched.
Co-authored-by: Billy Laws <blaws05@gmail.com>
`shaderImageGatherExtended` is required by the shader compiler, to avoid complications associated with making it optional and considering that it's supported by the vast majority of Vulkan mobile devices, it was made a mandatory feature.
This class will be entirely responsible for any interop with the shader compiler, it is also responsible for caching and compilation of shaders in itself.
We want to utilize features from C++ 20 ranges but they haven't been entirely implemented in libc++ so in the meantime we use the reference implementation for it which is Ranges v3.
Any primitive topologies that are directly supported by Vulkan were implemented but the rest were not and will be implemented with conversions as they are used by applications, they are:
* LineLoop
* QuadList
* QuadStrip
* Polygon
Translates all Maxwell3D vertex attributes to Vulkan with the exception of `isConstant` which causes the vertex attribute to return a constant value `(0,0,0,X)` which was trivial in OpenGL with `glDisableVertexAttribArray` and `glVertexAttrib4(..., 0, 0, 0, 1)` but we don't have access to this in Vulkan and might need to depend on undefined behavior or manually emulate it in a shader. This'll be revisited in the future after checking host GPU behavior.
`ENUM_STRING` can be used inside a `class`/`struct`/`union` for `enum`s contained within them. Making the function `static` allows doing this and doesn't require supplying a `this` pointer of the enclosing class for usage.
This being made implicit removes any confusion that all cases would need to be implemented and explicitly define that the CF should continue onto the 2nd switch-case when it cannot find any matches in the first one.
Implements the `isVertexInputRatePerInstance` register array which controls if the vertex input rate is either per-vertex or per-instance. This works in conjunction with the vertex attribute divisor for per-instance attribute repetition of attributes.
We order all registers in ascending order, a few registers namely `colorLogicOp`, `colorWriteMask`, `clearBuffers` and `depthBiasClamp` were erroneously not following this order which has now been fixed.
We inconsistently utilized `typeof` and `decltype` all over the codebase, this has now been fixed by uniformly using `decltype` as `typeof` is a GCC extension and not in the C++ standard alongside having the hidden side effect of removing references from the determined type.
Check for `vertexAttributeInstanceRateZeroDivisor` in `VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT` when the Maxwell3D register corresponding to the vertex attribute divisor is set to 0. If it isn't then it logs a warning and sets the value anyway which could result in UB since the only alternative is an exception that stops emulation which might not be optimal if the game mostly works fine without this, we will add a user-facing warning when we intentionally allow UB like this in the future.
Implement the infrastructure to depend on `VkPhysicalDeviceFeatures2` extended feature structures which can be utilized to retrieve the specifics of features from extensions. It is implemented in the form of `vk::StructureChain` with `vk::PhysicalDeviceFeatures2` that can be extended with any extension feature structures.
This implements everything in Maxwell3D vertex buffer bindings including vertex attribute divisors which require the extension `VK_EXT_vertex_attribute_divisor` to emulate them correctly, this has been implemented in the form of of a quirk. It is dynamically enabled/disabled based on if the host GPU supports it and a warning is provided when it is used by the guest but the host GPU doesn't support it.
The Maxwell3D `Address` class follows the big-endian register ordering for addresses while on the host we consume them in little-endian, the `IOVA` class is the host equivalent to the `Address` class with implicitly flipped 32-bit register ordering. It shares implicit decomposition semantics from `Address` due to similar requirements with a minor difference of being returned by reference rather than value as we want to have value setting semantics with implicit decomposition while we don't for `Address`.
The semantics of implicitly decomposing the `Address` class into a `u64` were determined to be appropriate for the class. As it is an integer type this effectively retains all semantics from using an integer directly for the most part.
Maxwell3D supports both independent and common color write masks like color blending but for common color write masks rather than having register state specifically for it, the state from RT 0 is extended to all RTs. It should be noted that color write masks are included in blending state for Vulkan while being entirely independent from each other for Maxwell, it forces us to use the `independentBlend` feature even when we are doing common blending unless the color write mask is common as well but to simplify all this logic the feature was made required as it supported by effectively all targeted devices.
Maxwell3D supports independent blending which has different blending per-RT and common blending which has the same blending for all RTs. There is a register determining which mode to utilize and we simply have two arrays of `VkPipelineColorBlendAttachmentState` for the RTs that we toggle between to make the transition between them extremely cheap.
Independent blending is supported by effectively every Vulkan 1.1 Android GPU, it gives us the ability to architecture Maxwell3D blending emulation better as we can avoid additional checks for independent blending state and having a fallback path for when the host doesn't support the feature.
A prior commit added the ability to utilize features with quirks but this implements the ability to require a feature be present on the host or an exception will be thrown. It allows us to make useful assumptions that result in a better architecture in certain cases.
Implements the infrastructure required to enable optional extensions set in `QuirkManager` alongside the required extensions in the `GPU` class. All extensions should be correctly resolved now and according to what the device supports.
The offset was incorrectly set to `0x4D` rather than `0x4ED` which is what it should be. This would've led to bugs in line width determination and likely broken any aliased line rendering entirely.
We selectively enable GPU features that we require as enabling all of them might result in extra driver overhead in certain circumstances. Setting them is handled by `QuirkManager` with the new `FEAT_SET` function that ties a quirk with a feature.
We stub alpha testing as it doesn't exist in Vulkan and few titles use it, it can be emulated in the future using a shader patch with manually discarding fragments failing the alpha test function but this'll be added in later as it isn't high priority at the moment and has associated overhead with it so other options might be explored at the time.
It is essential to know what quirks a certain GPU may have to debug an issue, these are now printed at startup into the log alongside all other GPU information. A new `QuirkManager::Summary` function was implemented to provide this functionality.
Implements a basic part of Vulkan blending state which are color logic operations applied on the framebuffer after running the fragment shader. It is an optional feature in Vulkan and not supported on any mobile GPU vendor aside from ImgTec/NVIDIA by default.
Any signals that lead to exception handling being triggered now attempt to flush all logs given that the log mutex is unoccupied, this is to mostly help logs be more complete when exiting isn't graceful.
A lot of calls in Maxwell3D register initialization ended up setting the register to 0 which should be implicit behavior and most calls would be eliminated by the redundancy check which had to be manually disabled. It was determined to be better to move this responsibility to the called function to initialize to state equivalent to the corresponding register being 0. All initialization calls with the argument as 0 have been removed now due to this, it was the vast majority of calls.
Maxwell3D Registers weren't initialized to the correct values prior, this commit fixes that by doing `HandleMethod` calls with all the register values being initialized. This is in contrast to the registers being set without calling the methods in `GraphicsContext` or otherwise resulting in bugs.
The function `GetFormat` was seemingly no longer required due to us never converting from a Vulkan format to a Skyline format, most conversions only went from Skyline to Vulkan and were generally lossy due to certain formats being missing in Vulkan and approximated using channel swizzles. As a result of this, it was pointless to maintain and has now been removed.
Maxwell3D registers relevant to the Vulkan Rasterizer state have been implemented aside from certain features such as per-face polygon modes that cannot be implemented due to Vulkan limitations. A quirk was utilized to dynamically support the provoking vertex being the last vertex as opposed to the first as well.
We require a way to track certain host GPU features that are optional such as Vulkan extensions, this is what the `QuirkManager` class does as it checks for all quirks and holds them allowing other components to branch based off these quirks.
Due to compiler alignment issues, the bitfield member `increment` of `MacroInterpreter::MethodAddress` was mistakenly padded and moved to the next byte. This has now been fixed by making its type `u16` like the member prior to it to prevent natural alignment from kicking in.
This commit added basic shader program registers, they simply track the address a shader is pointed to at the moment. No parsing of the shader program is done within them.
A thread local LoggerContext is now used to hold the output file stream instead of the `Logger` class. Before doing any logging operations, a LoggerContext must be initialized.
This commit will not build successfully on purpose.
Dividers after titles were missing in `ControllerActivity` which made it look inconsistent with `SettingsActivity` which did have them. They have now been added by extending `DividerItemDecoration` to be drawn before any `ControllerHeaderItem`.
The icons in these FABs had the same color as the FAB prior which led them to being invisible. This has been fixed by setting a white tint on them which makes the icons clearly visible.
Additional padding has been added to the text alongside making it be left-aligned rather than center-aligned and justified. A newline has also been added to the copyright notice for Skyline to make it look nicer.
We wanted the color of the modals used by the dialogs to be the same as our regular background color rather than a lighter grey. This has now been enforced with style attributes in the case of `AlertDialog` and `setBackground` in the case of `BottomSheetDialog`.
We inconsistently used `AppCompat`'s `AlertDialog` theme in Settings while using `MaterialComponents`'s theme in Controller Configuration. This has now been fixed by universally using the `MaterialComponents` theme.
The Skyline logo was added to the title area but it ended up being too distracting with a light theme as the logo was designed purely for a white background. Ultimately, even though it looked good with the dark theme we had to remove it.
Aligning the buttons to the bottom of the game image was determined to look odd due to the amount of padding between the title and buttons. They are now back to being below the title but the buttons have been resized with "Play" being a wide button while "Pin" has been replaced with Google Material Icons's "Add To Home Screen" icon and sized down to an icon-only button.
- Logo is now displayed next to the app name
- Remove search bar animation
- New color accent
- Improve visibility of controller binding setting's glyphs
This pushes a set of command buffers into the Host1x command FIFO allocated for the channel, returning fence thresholds that can be waited on for completion,
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.
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.
Guest-driven exiting could cause objects left on the heap due to a `std::longjmp` from high up in the host call stack, this has been fixed by introducing `ExitException` which implicitly unrolls the stack with the exception handling mechanism.
* Resolves dependency cycles in some components
* Allows for easier navigation of certain components like `span` which were especially large
* Some imports have been moved from `common.h` into their own files due to their infrequency
* Update licenses for dependent projects
* Add copyright notices (as provided)
* Revamp styling for `LicenseDialog`
* Fix invisible `PreferenceDialog` buttons in Settings
* Consolidating color variables into `colorPrimary`, `backgroundColor` and `backgroundColorVariant`
* Use `com.google.android.flexbox:flexbox:3.0.0` (Google Maven) rather than `com.google.android:flexbox:2.0.1` (Bintray)
* Clean Exiting was improved by implementing a robust system for when to abandon clean exiting and simply restart the process alongside moving clean exiting to the background when the application is quit by using the back button
* Audio is now automatically paused whenever the application is moved to the background and automatically resumed when it's brought to the foreground
* The system language setting had several errors and inconsistencies which have now been fixed, it's been brought more in line with HOS language (Albeit not entirely due to no region setting in Skyline)
* Fix a bug with `ThreadLocal` where the atomic `list` pointer was uninitialized resulting in a `SEGFAULT` during the destructor
* Fix handling `SA_EXPOSE_TAGBITS` bit being set in Android 12 `sigaction`
* Fix CMake bug using `CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE` when not supported causing `-fuse-ld=gold` to be emitted as a linker flag
* Support using `VIBRATOR_MANAGER_SERVICE` rather than `VIBRATOR_SERVICE` on Android 12
* Optimize Imports for Kotlin code
* Move away from deprecated APIs in Kotlin or explicitly mark where it's not possible
* Update SDK, NDK and libraries
* Enable Gradle Configuration Cache
These are used heavily in OpenGL games, which now, together with the
previous syncpoint changes, work perfectly. The actual implementation is
rather novel as rather than using a per-class state machine for all
methods we only use it for those that are known to be split across
GpEntry boundaries, as a result only a single bounds check is added to
the hot path of contiguous method execution and the performance loss is
negligible.
* Fix `AddClearColorSubpass` bug where it would not generate a `VkCmdNextSubpass` when an attachment clear was utilized
* Fix `AddSubpass` bug where the Depth Stencil texture would not be synced
* Respect `VkCommandPool` external synchronization requirements by making it thread-local with a custom RAII wrapper
* Fix linear RT width calculation as it's provided in terms of bytes rather than format units
* Fix `AllocateStagingBuffer` bug where it would not supply `eTransferDst` as a usage flag
* Fix `AllocateMappedImage` where `VkMemoryPropertyFlags` were not respected resulting in non-`eHostVisible` memory being utilized
* Change feature requirement in `AndroidManifest.xml` to Vulkan 1.1 from OGL 3.1 as this was incorrect
Allows the execution of multiple channels at the same time, with locking
being performed on the host GPU scheduler layer, address spaces can be
bound to one or more channels.
Infrastructure for always syncing textures has been introduced now, they will be synced prior to and after every execution. This does considerably reduce the performance alongside waiting on GPU execution to finish but it will be partially recouped once conditional syncing is performed.
* Move Shared Font TTFs to AAsset storage + Support external shared font loading from `/data/data/skyline.emu/data/fonts`
* Fix bug in `IApplicationFunctions::PopLaunchParameter` caused by ignoring `LaunchParameterKind`
* Fix bug with Choreographer causing it to be awoken and exit prior to the destruction of `PresentationEngine`
* Fix bug with `IDirectory::Read` where it used `inputBuf` for the output buffer rather than `outputBuf`
* Improve `GetFunctionStackTrace` logs when `dli_sname` or `dli_fname` are missing
* Support more RT Formats
Support for subpasses was added by reworking attachment reuse code to account for preserved attachments and subpass dependencies. A lot of RT formats were also added to allow SMO to boot up entirely, it should be noted that it doesn't render anything.
`FenceCycle` had a cyclic dependency which broke clean exit, we now utilize `std::weak_ptr<FenceCycle>` inside the `Texture` object. A minor fix for broken stack traces was also made caused by supplying a `nullptr` C-string to libfmt when a symbol was unresolved which caused an `abort` due to invocation of `strlen` with it.
This commit introduces the `CommandExecutor` which is responsible for creating and orchestrating a Vulkan command graph comprising of `CommandNode`s that construct all the objects required for rendering. As a result of the infrastructure provided by `CommandExecutor`, `ClearBuffers` could be implemented and be appropriately utilized.
A bug regarding scissors was also determined and fixed in the PR, the extent of them were previously inaccurate and this has now been fixed.
Note: We don't synchronize any textures from the guest for now as this would override the contents on the host, this'll be fixed with the appropriate write tracking but it also results in a black screen for anything that writes to FB
This commit fixes a major issue with command buffer allocation which would result in only being able to utilize a command buffer slot on the 2nd attempt to use it after it's freed, this would lead to a significantly larger amount of command buffers being created than necessary. It also fixes an issue with the command buffers not being reset after they were utilized which results in UB eventually.
Another issue was fixed with `FenceCycle` where all dependencies are only destroyed on destruction of the `FenceCycle` itself rather than the function where the `VkFence` was found to be signalled.
This commit implements a filter by type for any validation layer output, this allows filtering out any logs which may be unnecessary and additionally triggering a breakpoint as required.
An issue concerning the `NDEBUG` flag never being set was fixed, it's now supplied as a release compiler flag. The issue can manifest itself by always relying on a validation layer even though it shouldn't on release, this is why the validation layer was mistakenly disabled entirely previously by using `#ifndef` rather than `#ifdef`.
An issue with the initial layout of a texture being supplied as neither `VK_IMAGE_LAYOUT_UNDEFINED` or `VK_IMAGE_LAYOUT_PREINITIALIZED` was fixed, these cases are now handled by transitioning to those layouts after creating the image rather than supplying it within `initialLayout`.
Another issue was fixed regarding not maintaining a transformation after a surface has been destroyed and recreated existed and manifested itself when the user would go out of the app and come back in, they would see the surface having an identity transformation rather than the desired one.
Fixes bugs with the Texture Manager lookup, fixes `RenderTarget` address extraction (`low`/`high` were flipped prior), refactors `Maxwell3D::CallMethod` to utilize a case for the register being modified + preventing redundant method calls when no new value is being written to the register, and fixes the behavior of shadow RAM which was broken previously and would lead to incorrect arguments being utilized for methods.
Implement the groundwork for the texture manager to be able to report basic overlaps and be extended to support more in the future. The Maxwell3D registers `RenderTargetControl`, `RenderTarget` and a stub for `ClearBuffers` were implemented.
A lot of changes were also made to `GuestTexture`/`Texture` for supporting mipmapping and multiple array layers alongside significant architectural changes to `GuestTexture` effectively disconnecting it from `Texture` with it no longer being a parent rather an object that can be used to create a `Texture` object.
Note: Support for fragmented CPU mappings hasn't been added for texture synchronization yet
Utilize Boost Container's `small_vector` for optimizing allocations, fix certain implicit casting issues and make `ILogger` not output an additional newline in the log when the application supplies one at the end of the log
The format provided in `GraphicBuffer` can be misleading and is supplied as `None` by the Deko3D Swapchain, it instead supplies the real format in the `NvGraphicHandle` which we now utilize instead of the one in `GraphicBuffer`.
KTransferMemory needs to be reset to RW on destruction unlike KSharedMemory which is simply freed on destruction, not emulating this behavior accurately leads to `deko_examples` from `switch-examples` to lead to a SEGFAULT on selecting an example as it expects the memory to be R/W while it ends up being freed instead
The unique pointer to a device in the map was simply reset rather than deleting the entry from the map, this resulted in the device not being properly closed and when the device was reopened then the `emplace` was a NOP as the entry already existed. This resulted in a `nullptr` dereference down the line when an application attempted to issue an IOCTL to a device that was previously closed and reopened. This is known to occur in Deko3D as it recreates the context when loading an example which includes closing and reopening devices.
A hotfix for a nvdrv bug where an IOCTL with no input/output buffers would crash and a major `nvmap` bug which broke the `FromId` IOCTL as it didn't write back the handle ID, another minor bug existed in `nvhost` where the `ZCullGetInfo` IOCTL was `INOUT` rather than `OUT`.
A bug with NACPs was also fixed caused by incorrect padding for the `NacpData` structure which resulted in the `saveDataOwnerId` member being read incorrectly and as a result the save data folder being incorrect.
Co-authored-by: artem8086 <artemsvyatoha@gmail.com>
Swapped out the usages of frozen constexpr unordered maps for switch statements, which are very likely to be turned into jump tables given the nature of the enums used, resulting in better performance than a map
Unlike `ListPreference`, this preference class uses integers as its values instead of strings, avoiding unnecessary casting. It also doesn't require an array for values: in that case it will be using the clicked entry position as its value.
Using a u32 for the loop index prevents masking on all increments,
giving a moderate performance increase.
Passing methods as u32 parameters and stopping subChannel being passed
gives quite a significant increase when combined with the inlining
allowed by subchannel based engine selection.
The implementation of GPU channels and Host1X channels will be split up
as it allows a much cleaner implementation and less undefined behaviour
potential.
This will be required later for NVDEC/SMMU support and fixes many
significant issues in the previous implementation.
Based off of my 2.0.0/12.0.0 nvdrv REs.
The syncpoint manager has beeen given convinience functions for fences
which remove the need to access the raw id/threshold most of the time
and various accuracy fixes and cleanups to match HOS 12.0.0 have also
been done.
Implements the 'csrng:' service using C++ <random>'s Mersenne Twister, this does make it insecure for cryptographic purposes but it is pointless to attempt to do this regardless as we cannot ensure that the guest will run in a secure environment which cannot be mutated by an attacker. Used by Prison Princess, Pokemon Cafe Mix, Paint your Pet and more.
Encountered in 不如帰大乱 when `HOS-3` is awoken at the same time as `HOS-0` called `SvcSetThreadCoreMask` resulting in a deadlock where `HOS-0` owns `HOS-3`'s `coreMigrationMutex` while `HOS-3` owns the core mutex with the both of them attempting to lock the other mutex
We've moved from using an AAR for Mbed TLS to a submodule as the AAR was packaged manually and used from a local repository which ended up being very hacky and resulted in Linter errors, it could also not be updated with ease as it would need to be repackaged. All of these issues have been solved by moving to a git submodule tied to the official Mbed TLS GitHub repository.
Sticky transforms have been stubbed, as they are on HOS/Android. Certain titles like Xenoblade Chronicles end up setting the sticky transform even if it doesn't do anything, as a result of this we cannot throw an exception for it and stub it without an exception (Aside from the cases where the value isn't recognized).
The following GraphicBufferProducer transactions were implemented:
* `SetBufferCount`
* `DetachBuffer`
* `DetachNextBuffer`
* `AttachBuffer`
It should be noted that `preallocatedBufferCount` (previously `hasBufferCount`) and `activeSlotCount` were adapted accordingly with how they were effectively the same value as all active buffers were preallocated prior but now there can be a non-preallocated active slot.
Additionally, a bug has been fixed where `SetPreallocatedBuffer` has the graphic buffer as an optional argument whereas it was treated as a mandatory argument prior and could lead to a SEGFAULT if an application were to not pass in a buffer.
VI/IHOSBinder suffered from major inaccuracies in their function due to being quickly thrown together initially with little concern for accuracy, this has now been fixed with them being substantially more accurate now.
`ENUM_STRING` now has a unified implementation in <common/macros.h> with a documented format and can be used throughout the codebase.
A major performance regression was added in the Host1X Syncpoint revamp as it did a syscall if there were any waiters during `Increment` even if they would just be woken up and go back to sleep as the threshold wasn't hit. It has now been optimized to only do a wake if any waiting thread needs to be awoken.
There was also a bug concerning increment where it would perform actions corresponding to the previous increment rather than the current one which has also been fixed.
We used instantaneous values for FPS previously which led to a lot of variation in it and the inability to determine a proper FPS value due to constant fluctuations. All FPS values are now averaged to allow reading out a stable value and a deviation statistic has been added for the frame-time to judge judder and frame-pacing which allows for a significantly better measure of overall performance. The formatting for all the floating-point numbers is now fixed-point to prevent shifting of position due to decimal digits becoming 0.
Support for the following parameters was added to `QueueBuffer`:
* Earliest Present Timestamp
* Swap Interval
* Crop
* Scaling Mode
* Transform
* Frame ID (Not returned to guest yet)
We utilize ANativeWindow APIs directly to achieve all of this in an efficient manner since HWC will be used directly for it, we do plan to introduce Vulkan equivalents for all of these operations later down the line for a port to non-Android platforms.
We had issues when combining host and guest presentation since certain configurations in guest presentation such as double buffering were very unoptimal for the host and would significantly affect the FPS. As a result of this, we've now made host presentation have its own presentation textures which are copied into from the guest at presentation time, allowing us to change parameters of the host presentation independently of the guest.
We've implemented the infrastructure for this which includes being able to create images from host GPU memory using VMA, an optimized linear texture sync and a method to do on-GPU texture-to-texture copies.
We've also moved to driving the V-Sync event using AChoreographer on its on thread in this PR, which more accurately encapsulates HOS behavior and allows games such as ARMS to boot as they depend on the V-Sync event being signalled even when the game isn't presenting.
This commit reworks the `Texture` class to include a Vulkan Image backing that can be optionally owning or non-owning and swapped in with consideration for Vulkan image layout, it also adds CPU-sided synchronization for the texture objects with FenceCycle. It also makes the appropriate changes to `PresentationEngine` and `GraphicBufferProducer` to work with the new `Texture` class while setting the groundwork for supporting swapchain recreation. It also fixes a log in `IpcResponse` and improves the display mode selection algorithm by further weighing refresh rate.
Implements a wrapper over fences to track a single cycle of activation, implement a Vulkan memory manager that wraps the Vulkan-Memory-Allocator library and a command scheduler for scheduling Vulkan command buffers
This commit makes GraphicBufferProducer significantly more accurate by matching the behavior of AOSP alongside mirroring the tweaks made by Nintendo.
It eliminates a lot of the magic structures and enumerations used prior and replaces them with the correct values from AOSP or HOS.
There was a lot of functional inaccuracy as well which was fixed, we emulate the exact subset of HOS behavior that we need to. A lot of the intermediate layers such as GraphicBufferConsumer or Gralloc/Sync are not emulated as they're pointless abstractions here.
This commit adds in VkSurface/VkSwapchain initialization and recreation. It also adapts GraphicsBuffferProducer and Texture to fit in with those changes but it doesn't yet implement presenting those buffers nor uploading guest buffers onto the host.
Vulkan Device initialization is handled now, it supports required extensions but support for optional extensions/features/properties will come in later when we require those. In addition, we now correctly report the version of Skyline to Vulkan which can be accessed from debugging tools.
There's also a minor change regarding the search pattern for `SkylineLibraries` which now only searches in headers of libraries and it also explicitly excludes the redundant `vulkan.hpp` from the `Vulkan-Headers` repository.
The GPU class has been extended in this for Vulkan initialization, this is done to the point of initializing the instance alongside loading in `VK_LAYER_KHRONOS_validation` which is also now packed into all Debug APKs for Skyline. In addition, `VK_EXT_debug_report` is also initialized and it's output is piped directly into the Logger.
A minor change regarding the type of the `Fps` and `Frametime` globals was changed to `skyline::i32`s which is a more suitable type due to those having a smaller chance of overflowing while being signed as Java doesn't have unsigned integral types.
As both of these are in the same memory segment they have no individual
alignment requirements, this created a bug in
にゃんらぶ~私の恋の見つけ方~ where the data segment would be larger
than the game expected and invalid command line arguments would be read.
armed.
It was discovered during testing of 'Hatsune Miku Project DIVA: Mega Mix'
that if a thread was starting while preemption was being enabled a NULL
pointer dereference could occur in the timer_settime call as
timer_create may not have been called yet.
This is used by games before calling into nvdec in order to clock up the
HW module, it can also be used to request a RAM frequency. Since we
obviously don't emulate the hardware down to this level a basic stub
that provides the correct reponses is enough.
Fixes a crash on first level of Super Mario Odyssey.
We used a custom version of Vulkan-Hpp which split the files a lot prior to avoid any developers needing to manually set IDE settings for IntelliJ to work but this wasn't practical due to how it required modifications to Vulkan-Hpp's generator which would make maintenance extremely difficult. It was determined that we should just add the requirement for changing the IDE settings and use Vulkan-Hpp directly.
An RAII scoped trace was used for SvcWaitSynchronization but it was placed within a condition scope which led to an incorrect lifetime for the traces. Minor changes regarding the CR not affecting functionality were made aside from that.
We decided to restructure Skyline to draw a layer of separation between guest and host GPU. We're reserving the `gpu` namespace and directory for purely host GPU and creating a new `soc` directory and namespace for emulation of parts of the X1 SoC which is currently limited to guest GPU but will be expanded to contain components like the audio DSP down the line.
This just disables all compiler warnings generated while compiling TZCode as those are irrelevant while compiling Skyline and need to be tackled in that repository.
This fixes audio stuttering which occurred on certain BT audio devices by requesting an exclusive stream from Oboe alongside a low-latency stream.
Co-authored-by: Billy Laws <blaws05@gmail.com>
Add Tracing for SVCs, Services, NVDRV, and Synchronization Primitives. In addition, fix `TRACE_EVENT_END("guest")` being emitted when a signal is received while being in the guest rather than host which would cause an exception. This commit also disables warnings for the Perfetto library as we do not control fixing them.
This extend a descriptor table for the SVCs with names for every SVC alongside their function pointer. The names are then used for logging and eventually tracing.
This moves from using std::function with a this pointer binding (which would likely cause a heap allocation) to returning the this pointer in a structure which implements operator() to do the call with it. It also moves to using const char* for strings from std::string_view which was pointless in this scenario due to it's usage being limited to being a C-string for the most part, it also integrates the class name directly into the string which allows us to avoid runtime string concatenation in libfmt and RTTI for finding the class name.
* Improve KMemory Comments
* Add parameter prefix 'p-' to `KPrivateMemory::UpdatePermission`
* Fix the missing trailing double quote in missing service prints, this was due to `stringName` being padded with extra 0s
Mainly just adapts the rest of time to add some things missed in the
initial commit as they required TZ, everything else is just renames from
switchbrew and comments.
This serves as an extension to the initial time commit and combined
they provide a complete implementation of everything application facing
in time.
psc:ITimeZoneService and glue:ITimeZoneService are used to convert
between POSIX and calendar times according to the device location.
Timezone binaries are used during the conversion, details of them can
be read about in the previous commit.
This is based off my own glue RE and Thog's time RE.
This reimplements our time backend to be significantly more accurate to
the real PSC and provides complete implementations for every time IPC
allowing many newer games to work properly.
Time is unique in its use of glue services, the core sysmodule is fully
isolated and doesn't interface with any other services. Glue is instead
used where that is needed (e.g. for fetching settings), this distinction
is also present in our implementation.
Another unique feature of time is its global state, as time is
calibrated from the start of the service its state cannot be lost as
that would result in the application offsetting time incorrectly
whenever it closed a session.
A large proportion of this is based off of Thog's 9.0.0 PSC reversing.
These are used for timezone conversions between POSIX and calander time.
Tzdata is in exactly the same format as HOS to allow loading sysarchives
in the future if needed. See its README for more info.
Details on tzcode can be found in its own repo, there are several
changes done Vs the base release to allow for HOS compat.
These only implement the subset of VFS needed for time, implementing
more is difficult due to some issues in the AAsset API which make
support quite ugly. The abstract asset filesystem can be accessed by
services through the OS class allowing other implementations to be used
in the future.
There was a mistake in the code-style refactor where the signature in the instruction encoding of `MRS` was set to `0xD54` instead of `0xD53` which would cause a SIGILL (Illegal Instruction) for devices which had their HW timer frequency equivalent to the Switch (19.2MHz) as a modified `MRS` would be deployed there. This issue should not affect devices which perform clock rescaling as the `MRS` instruction there is encoded by the assembler.
Many users of VFS didn't check for nullptr or 0 results leading to
various potential issues, to mitigate this introduce error checking to
VFS by default. The original variants can still be used through the
*Unchecked family of functions.
This allows better validation and simplified default argument handling.
Could also be useful in the future when we switch to proper VFS error
reporting.
* Pushbuffer data is now stored in a member buffer to avoid reallocating
it for each pushbuffer which hampered performance before.
* Don't prefetch pushbuffers as it puts unnecessary load on the guest
thread that is better suited for the GPFIFO thread.
* Clean up some misc code to avoid pointless casts of a 4 byte object
and handle GPFIFO control opcodes.
NvHostEvents were renamed to SyncpointEvents which is a much clearer
name that more accurately describes them. Locking is needed as IOCTLs
can be called asynchronously and so event registration and signalling
can race.
The following scheduler bugs were fixed:
* It was assumed that all non-cooperative `Rotate` calls were from a preemptive yield and changed the state of `KThread::isPreempted` incorrectly which could lead to UB, an example of a scenario with it would be:
* * Preemptive thread A gets a signal to yield from cooperative thread B due to it being ready to schedule and higher priority
* * A complies with this request but there's an assumption that the signal was actually from it's preemption timer therefore it doesn't reset it (As it isn't required if the timer was responsible for the signal)
* * A receives the actual preemption signal a while later, causing UB as the signal handler is invoked twice
* `Scheduler::UpdatePriority`
* * A check for `currentIt == core->queue.begin()` existed which caused an incorrect early return
* * The preemption timer was armed correctly when a priority transition from cooperative priority -> preemption priority occurred but not disarmed when a transition from preemption priority -> cooperative priority occurred
* * The timer was unnecessarily disarmed in the case of updating the priority of a non-running thread, this isn't as much a bug as it is just pointless
* Priority inheritance in `KProcess::MutexLock` is fundamentally broken as it performs UB with `waitThread` being accessed prior to being assigned
* When a thread sets its own priority using `SvcSetThreadCoreMask` and its current core is no longer in the affinity mask, it wouldn't actually move to the new thread until the next time the thread is load balanced
This addresses all CR comments including more codebase-wide changes arising from certain review comments like proper usage of its/it's and consistent contraction of it is into it's.
An overhaul was made to the presentation and formatting of `KThread.h` and `LoadBalance` works has been superseded by `GetOptimalCoreForThread` which can be used alongside `InsertThread` or `MigrateToCore`. It makes the API far more atomic and neater. This was a major point of contention for the design prior, it's simplified some code and potentially improved performance.
The case of a thread not being in the core queue during a non-cooperative core affinity change would break things as the thread was non-conditionally removed and inserted, this has been fixed by adding a check to see if the thread exists in the core's queue prior to migration. In addition, `yieldWithCoreMigration` was broken by the previous commit as the fallthrough was intentional and removing it cause core migration without a yield which led to breakage in certain circumstances. The mutex locking logic was also improved in `ConditionalVariableWait` to use atomics in a more effective manner with less atomic operations being performed overall.
The code region's size was previously set at the same value as it is for 36-bit ASes, this value is inadequate for certain larger games and needed to be expanded. We've chosen 4GiB as the new value which should easily encompass all Switch games.
The SVCs improvements are as follows:
* Make SVC logs more concise for:
* * `SleepThread`
* * `ClearEvent`
* * `CloseHandle`
* * `ResetSignal`
* * `WaitSynchronization` (Special case for single handle)
* * `ArbitrateLock`
* * `ArbitrateUnlock`
* * `WaitProcessWideKeyAtomic`
* * `SignalProcessWideKey`
* Fix unintentional fallthrough into `yieldWithoutCoreMigration` from `yieldWithCoreMigration` in `SleepThread`
* Return `result::InvalidState` when an unsignalled handle is reset in `ResetSignal`
* Return `Result{}` (Success) in `CancelSynchronization`
* Do not return `result::InvalidCurrentMemory` in `ArbitrateLock` as it's not a failure condition
* Make `count` in `WaitProcessWideKeyAtomic` a `i32` from a `u32`, zero and all negative values result in waking all waiters
The entirety of the address arbiter is implemented in this commit, all three arbitration types: `WaitIfLessThan`, `DecrementAndWaitIfLessThan` and `WaitIfEqual`, and all three signal types: `Signal`, `SignalAndIncrementIfEqual` and `SignalAndModifyBasedOnWaitingThreadCountIfEqual` have been implemented.
This allows any application which uses levent (Light Events) to function which includes titles such as ARMS.
We did not support migration of threads which were running in a non-cooperative manner, this was partially due to the dependence on per-core conditional variables rather than per-thread which made this harder to do programmatically. This has been fixed by moving to per-thread cvars and therefore the limitation can be removed, this feature is used by Unity games.
SvcClearEvent previously set the `signalled` flag directly rather than
calling `ResetSignal`, which skipped the locking necessary to make it
globally visible. Switch it to use `ResetSignal` to fix this.
We've moved to using RS and GS from ASCII as delimiters rather than
'\n' and '|', this allows more robust parsing and increases the
readability of the log files
This prevents a race where two threads could read at the same time and
end up using the wrong IV leading to garbage data being read. This
caused crashes in several games including Celeste.
This was causing a significant amount of sched thrashing and pinning a
core to 100% as games constantly updated audren, now change it to only
signal on buffer release.
This caused the menus in Sonic Mania to be nonfunctional, futhermore,
default init is not ran for the input structs so the default max
definition in CommonHeader never actually applied.
CircularQueue was looping around too early resulting in the wrong
pushbuffers being used. The debug logging is useful for interpreting the
GPU method call logs.
Exefs loading was changed to check if an NSO exists before trying to
read it, preventing exceptions that get annoying while debugging.
* 'Fix' memory accounting to not measure reserved regions
* Fix some copy bugs introduced by switch to span
* Correct remap the behaviour of Modify so it actually works
An exceptional signal handler allows us to convert an OS signal into a C++ exception, this allows us to alleviate a lot of crashes that would otherwise occur from signals being thrown during execution of games and be able to handle them gracefully.
* Fix alignment handling in NvHostAsGpu::AllocSpace
* Implement Ioctl{2,3} ioctls
These were added in HOS 3.0.0 in order to ease handling ioctl buffers.
* Introduce support for GPU address space remapping
* Fix nvdrv and am service bugs
Syncpoints are supposed to be allocated from ID 1, they were allocated
at 0 before. The ioctl functions were also missing from the service map
* Fix friend:u service name
* Stub NVGPU_IOCTL_CHANNEL_SET_TIMESLICE
* Stub IManagerForApplication::CheckAvailability
* Add OsFileSystem Directory support and add a size field to directory entries
The size field will be needed by the incoming HOS IDirectory support.
* Implement support for IDirectory
This is used by applications to list the contents of a directory.
* Address feedback
This patch reduces the burden of adding services significantly, rather
than having to create an enum entry and add strings in the constructor
it will all be determined at runtime through RTTI. A macro is also used
in the service creation case to reduce clutter.
* Fix NvHostCtrl:EventSignal event ID parsing
* Divide the audout buffer length by the sample size
* Correct audout channel quantity handling
* A few bugfixes for audio tracks
* * Correctly lock in CheckReleasedBuffers and only call the callback once
* * Check if the identifier queue is empty before accessing it's iterator
* Refactor audio to better fit the codestyle
* Explictly specify reference when using GetReference
* Fix CheckReleasedBuffers
This commit significantly increases the accuracy of the prior HID code due to testing on the Switch. It is now fully accurate in all supported scenarios, them being assignment mode, orientation, color writes and system properties. In addition, review comments were addressed and fixed in the PR.
This fixes a Joy-Con Pair bug which caused a crash when a partner device was set to none while being set as a partner. In addition, the following HID service functions were implemented:
* GetSupportedNpadStyleSet
* ActivateNpadWithRevision
* GetNpadJoyHoldType
* AcquireNpadStyleSetUpdateEventHandle
This commit adds support to the C++ end of things for controller configuration. It isn't targeting being 1:1 to HOS for controller assignment but is rather based on intuition of how things should be.
This commit adds in the UI for Controller Configuration to Settings, in addition to introducing the storage and loading of aforementioned configurations to a file that can be saved/loaded at runtime. This commit also fixes updating of individual fields in Settings when changed from an external activity.
This commit focuses on making the UI completely usable using a controller so that a user won't have to switch between their device's touch screen and a controller constantly.
This commit refactors the C++ end of Input so it'll be in line with the rest of the codebase and be ready for the extension with multiple players and controller configuration.
This commit contains the Kotlin side of the initial Input implementation, this is based on the work done in the `hid` branch in `bylaws/skyline`.
Co-authored-by: ◱ PixelyIon <pixelyion@protonmail.com>
This commit contains the C++ side of the initial Input implementation, this is based on the work done in the `hid` branch in `bylaws/skyline`.
Co-authored-by: ◱ PixelyIon <pixelyion@protonmail.com>
interpreter.
The Maxwell 3D engine handles all 3D rendering, currently only non
rendering related methods are implemented. Macros are small pieces of
code that run on the GPU and allow methods to be quickly called for
things like instanced drawing.
These are used to allow the CPU to synchronise with the GPU as it
reaches specific points in its command stream.
Also fixes an nvmap bug where a struct was incorrect.
bugs
An engine is effectively a HW block in the GPU, the main one is the
Maxwell 3D which is used for 3D graphics. Engines can be bound to
individual subchannels and then methods within them can be called
through pushbuffers.
The engine side of the GPFIO is also included, it currently does nothing
but will need to be extended in the future with semaphores.
* Rework VFS to support creating and writing files and introduce OsFileSystem
OsFileSystem abstracts a directory on the device using the filesystem API.
This also introduces GetEntryType and changes FileExists to use it.
* Implement the Horizon FileSystem APIs using our VFS framework
Horizon provides access to files through its IFileSystem class, we can
closely map this to our vfs::FileSystem class.
* Add support for creating application savedata
This implements basic savedata creation using the OsFileSystem API. The
data is stored in Skyline's private directory is stored in the same
format as yuzu.
* Make sure icons have a 1:1 ratio
* Use recyclerview padding to increase grid edge margins
* Fix race condition in searching roms
* Use notify insert for adapter
The GPU has it's own seperate address space to the CPU. It is able to
address 40 bit addresses and accesses the system memory. A sorted vector
has been used to store blocks as insertions are not very frequent.
unmapped regions
svcQueryMemory will return a valid descriptor for anything in the
address space, from 0 to 1 << addrSpaceBits, this was handled
incorrectly before and we were only returning descriptors if the
address was in a mapped region.
If an address in an unmapped region is requested then the extents of the
unmapped region up to the address space end are returned. If the address
requested is outside of the address space then the extents of the
inaccessible address space are returned.
To facilitate this support was added to MemoryManager::Get for
generating the extents of unmapped regions using the chunk list.
As the stack is automatically mapped in the guest by `clone` we do not
need to explicitly map it. This adds a flag to solve the issue.
Also mark the stack as stack rather than reserved.
Not zeroing the sample buffer causes issues when a voice is started but
is playing no samples. The system event handling was also reworked
according to Thog's info.
This fixes two bugs in IPC that were discovered when running Puyo Puyo
Tetris.
The CloneCurrentObject control IPC will now correctly return the handle
of the newly created object through move handles, rather than pushing it
as a result.
The size array of u16s with the sizes of each C buffer is now taken into
account when reading them. Before this change C buffers were entirely
broken.
This gives some useful warnings for less significant issues.
Warnings for reordering are left disabled as they are rather pedantic
and serve little benefit.
This implements the base account service and stubs
InitializeApplicationInfoV0 which is used by Puyo Puyo Tetris. Support
for the entirety of account services will be added in the future.
lm is used by applications to print messages to the system log. Log
messages are made up of a header and then several fields containing
metadata or string messages.
In the case of am, IStorage is used to exchange buffers of data such
as application launch parameters or an applets result. It has no
relation to fsp-srv's IStorage.