Compare commits

..

13 Commits

Author SHA1 Message Date
fb55f57da7 Horizon: Migrate wlan and stubs latest services (#5708)
* Horizon: Migrate wlan and stubs latest services

This PR migrate empty wlan services, values are found by RE.
Latest firmwares added some other services which are now stubbed and up-to-date.

* Fix imports ordering
2023-09-20 22:55:27 +02:00
44862dce3e Stub unsupported BSD socket options (#5670)
* Stub unsupported BSD socket options

* Span.Clear
2023-09-19 19:35:56 +02:00
e601419bd4 make cheat list binding public (#5697) 2023-09-19 16:51:56 +00:00
d6bc0de785 use compiled bidning for localizations (#5684) 2023-09-18 22:20:59 +02:00
9f26fd3600 remove some usages of reflection binding (#5686) 2023-09-18 22:09:22 +02:00
88df636c87 Replace ShaderOutputLayer with equivalent ShaderViewportIndexLayerEXT capability (#5683) 2023-09-16 18:49:13 +02:00
7ccff037e8 Fix some Vulkan validation errors (mostly related to barriers) (#5603)
* Replace image barriers inside render pass with more generic memory barrier

* Remove forceStorage since it was creating images with storage bit for formats that are not StorageImage compatible

* Add missing flags on subpass dependency

* Don't call vkCmdSetScissor with a scissor count of 0

* One semaphore per swapchain image

* Remove compute stage from read to write barriers

* Try to improve Pipeline.Barrier nonsense

* Set PipelineStateFlags based on supported stages
2023-09-14 19:58:11 +02:00
a745913329 Fix gl_Layer to geometry shader change not writing gl_Layer (#5682)
* Fix gl_Layer to geometry shader change not writing gl_Layer

* Shader cache version bump
2023-09-14 14:53:53 -03:00
e6700b314f lbl: Migrate service to Horizon (#5628)
* lbl: Migrate service to Horizon

* Fix formatting

* Addresses gdkchan's feedback

* Fix comments
2023-09-14 09:50:19 +02:00
e2cfe6fe44 Fix shader GlobalToStorage pass when base address comes from local or shared memory (#5668)
* Fix shader GlobalToStorage pass when base address comes from local or shared memory

* Shader cache version bump
2023-09-11 01:22:18 +00:00
210f475484 Replacing 'Assembly.GetExecutingAssembly()' with 'Type.Assembly' (#5545) 2023-09-07 14:10:58 +02:00
ddb6493896 Delete ResourceAccess (#5626)
* Delete ResourceAccess

* Set write flag for vertex/geometry as compute output buffers
2023-09-05 22:59:21 +02:00
f631933e60 Add macOS Headless release workflow (#5272)
* Add macOS Headless release workflow

* Add MACH-O check before applying signature

* Rename script for consistency

* Remove redundant compiler flag

* Fix release.yml arguments + names

* Update headless.sh to include changes of pr #5398
2023-09-05 01:28:44 +02:00
84 changed files with 1086 additions and 426 deletions

View File

@ -135,9 +135,13 @@ jobs:
id: git_short_hash
run: echo "result=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
- name: Publish macOS
- name: Publish macOS Ryujinx.Ava
run: |
./distribution/macos/create_macos_build.sh . publish_tmp publish_ava ./distribution/macos/entitlements.xml "${{ env.RYUJINX_BASE_VERSION }}" "${{ steps.git_short_hash.outputs.result }}" "${{ matrix.configuration }}" "-p:ExtraDefineConstants=DISABLE_UPDATER"
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish_ava ./distribution/macos/entitlements.xml "${{ env.RYUJINX_BASE_VERSION }}" "${{ steps.git_short_hash.outputs.result }}" "${{ matrix.configuration }}" "-p:ExtraDefineConstants=DISABLE_UPDATER"
- name: Publish macOS Ryujinx.Headless.SDL2
run: |
./distribution/macos/create_macos_build_headless.sh . publish_tmp_headless publish_headless ./distribution/macos/entitlements.xml "${{ env.RYUJINX_BASE_VERSION }}" "${{ steps.git_short_hash.outputs.result }}" "${{ matrix.configuration }}" "-p:ExtraDefineConstants=DISABLE_UPDATER"
- name: Upload Ryujinx.Ava artifact
uses: actions/upload-artifact@v3
@ -145,3 +149,10 @@ jobs:
name: ava-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
path: "publish_ava/*.tar.gz"
if: github.event_name == 'pull_request'
- name: Upload Ryujinx.Headless.SDL2 artifact
uses: actions/upload-artifact@v3
with:
name: sdl2-ryujinx-headless-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
path: "publish_headless/*.tar.gz"
if: github.event_name == 'pull_request'

View File

@ -188,15 +188,19 @@ jobs:
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
shell: bash
- name: Publish macOS
- name: Publish macOS Ryujinx.Ava
run: |
./distribution/macos/create_macos_build.sh . publish_tmp publish_ava ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish_ava ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release
- name: Publish macOS Ryujinx.Headless.SDL2
run: |
./distribution/macos/create_macos_build_headless.sh . publish_tmp_headless publish_headless ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release
- name: Pushing new release
uses: ncipollo/release-action@v1
with:
name: ${{ steps.version_info.outputs.build_version }}
artifacts: "publish_ava/*.tar.gz"
artifacts: "publish_ava/*.tar.gz, publish_headless/*.tar.gz"
tag: ${{ steps.version_info.outputs.build_version }}
body: "For more information about this release please check out the official [Changelog](https://github.com/Ryujinx/Ryujinx/wiki/Changelog)."
omitBodyDuringUpdate: true

View File

@ -0,0 +1,111 @@
#!/bin/bash
set -e
if [ "$#" -lt 7 ]; then
echo "usage <BASE_DIR> <TEMP_DIRECTORY> <OUTPUT_DIRECTORY> <ENTITLEMENTS_FILE_PATH> <VERSION> <SOURCE_REVISION_ID> <CONFIGURATION> <EXTRA_ARGS>"
exit 1
fi
mkdir -p "$1"
mkdir -p "$2"
mkdir -p "$3"
BASE_DIR=$(readlink -f "$1")
TEMP_DIRECTORY=$(readlink -f "$2")
OUTPUT_DIRECTORY=$(readlink -f "$3")
ENTITLEMENTS_FILE_PATH=$(readlink -f "$4")
VERSION=$5
SOURCE_REVISION_ID=$6
CONFIGURATION=$7
EXTRA_ARGS=$8
if [ "$VERSION" == "1.1.0" ];
then
RELEASE_TAR_FILE_NAME=sdl2-ryujinx-headless-$CONFIGURATION-$VERSION+$SOURCE_REVISION_ID-macos_universal.tar
else
RELEASE_TAR_FILE_NAME=sdl2-ryujinx-headless-$VERSION-macos_universal.tar
fi
ARM64_OUTPUT="$TEMP_DIRECTORY/publish_arm64"
X64_OUTPUT="$TEMP_DIRECTORY/publish_x64"
UNIVERSAL_OUTPUT="$OUTPUT_DIRECTORY/publish"
EXECUTABLE_SUB_PATH=Ryujinx.Headless.SDL2
rm -rf "$TEMP_DIRECTORY"
mkdir -p "$TEMP_DIRECTORY"
DOTNET_COMMON_ARGS=(-p:DebugType=embedded -p:Version="$VERSION" -p:SourceRevisionId="$SOURCE_REVISION_ID" --self-contained true $EXTRA_ARGS)
dotnet restore
dotnet build -c "$CONFIGURATION" src/Ryujinx.Headless.SDL2
dotnet publish -c "$CONFIGURATION" -r osx-arm64 -o "$TEMP_DIRECTORY/publish_arm64" "${DOTNET_COMMON_ARGS[@]}" src/Ryujinx.Headless.SDL2
dotnet publish -c "$CONFIGURATION" -r osx-x64 -o "$TEMP_DIRECTORY/publish_x64" "${DOTNET_COMMON_ARGS[@]}" src/Ryujinx.Headless.SDL2
# Get rid of the support library for ARMeilleure for x64 (that's only for arm64)
rm -rf "$TEMP_DIRECTORY/publish_x64/libarmeilleure-jitsupport.dylib"
# Get rid of libsoundio from arm64 builds as we don't have a arm64 variant
# TODO: remove this once done
rm -rf "$TEMP_DIRECTORY/publish_arm64/libsoundio.dylib"
rm -rf "$OUTPUT_DIRECTORY"
mkdir -p "$OUTPUT_DIRECTORY"
# Let's copy one of the two different outputs and remove the executable
cp -R "$ARM64_OUTPUT/" "$UNIVERSAL_OUTPUT"
rm "$UNIVERSAL_OUTPUT/$EXECUTABLE_SUB_PATH"
# Make it libraries universal
python3 "$BASE_DIR/distribution/macos/construct_universal_dylib.py" "$ARM64_OUTPUT" "$X64_OUTPUT" "$UNIVERSAL_OUTPUT" "**/*.dylib"
if ! [ -x "$(command -v lipo)" ];
then
if ! [ -x "$(command -v llvm-lipo-14)" ];
then
LIPO=llvm-lipo
else
LIPO=llvm-lipo-14
fi
else
LIPO=lipo
fi
# Make the executable universal
$LIPO "$ARM64_OUTPUT/$EXECUTABLE_SUB_PATH" "$X64_OUTPUT/$EXECUTABLE_SUB_PATH" -output "$UNIVERSAL_OUTPUT/$EXECUTABLE_SUB_PATH" -create
# Now sign it
if ! [ -x "$(command -v codesign)" ];
then
if ! [ -x "$(command -v rcodesign)" ];
then
echo "Cannot find rcodesign on your system, please install rcodesign."
exit 1
fi
# NOTE: Currently require https://github.com/indygreg/apple-platform-rs/pull/44 to work on other OSes.
# cargo install --git "https://github.com/marysaka/apple-platform-rs" --branch "fix/adhoc-app-bundle" apple-codesign --bin "rcodesign"
echo "Using rcodesign for ad-hoc signing"
for FILE in "$UNIVERSAL_OUTPUT"/*; do
if [[ $(file "$FILE") == *"Mach-O"* ]]; then
rcodesign sign --entitlements-xml-path "$ENTITLEMENTS_FILE_PATH" "$FILE"
fi
done
else
echo "Using codesign for ad-hoc signing"
for FILE in "$UNIVERSAL_OUTPUT"/*; do
if [[ $(file "$FILE") == *"Mach-O"* ]]; then
codesign --entitlements "$ENTITLEMENTS_FILE_PATH" -f --deep -s - "$FILE"
fi
done
fi
echo "Creating archive"
pushd "$OUTPUT_DIRECTORY"
tar --exclude "publish/Ryujinx.Headless.SDL2" -cvf "$RELEASE_TAR_FILE_NAME" publish 1> /dev/null
python3 "$BASE_DIR/distribution/misc/add_tar_exec.py" "$RELEASE_TAR_FILE_NAME" "publish/Ryujinx.Headless.SDL2" "publish/Ryujinx.Headless.SDL2"
gzip -9 < "$RELEASE_TAR_FILE_NAME" > "$RELEASE_TAR_FILE_NAME.gz"
rm "$RELEASE_TAR_FILE_NAME"
popd
echo "Done"

View File

@ -1,6 +1,7 @@
using Avalonia.Data;
using Avalonia.Data.Core;
using Avalonia.Markup.Xaml;
using Avalonia.Markup.Xaml.MarkupExtensions;
using Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings;
using System;
namespace Ryujinx.Ava.Common.Locale
@ -18,11 +19,20 @@ namespace Ryujinx.Ava.Common.Locale
{
LocaleKeys keyToUse = Key;
ReflectionBindingExtension binding = new($"[{keyToUse}]")
{
Mode = BindingMode.OneWay,
Source = LocaleManager.Instance,
};
var builder = new CompiledBindingPathBuilder();
builder.SetRawSource(LocaleManager.Instance)
.Property(new ClrPropertyInfo("Item",
obj => (LocaleManager.Instance[keyToUse]),
null,
typeof(string)), (weakRef, iPropInfo) =>
{
return PropertyInfoAccessorFactory.CreateInpcPropertyAccessor(weakRef, iPropInfo);
});
var path = builder.Build();
var binding = new CompiledBindingExtension(path);
return binding.ProvideValue(serviceProvider);
}

View File

@ -6,9 +6,11 @@
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="{locale:Locale ErrorWindowTitle}"
xmlns:views="using:Ryujinx.Ava.UI.Applet"
Width="450"
Height="340"
CanResize="False"
x:DataType="views:ErrorAppletWindow"
SizeToContent="Height"
mc:Ignorable="d"
Focusable="True">
@ -38,7 +40,7 @@
Grid.Column="1"
Margin="10"
VerticalAlignment="Stretch"
Text="{ReflectionBinding Message}"
Text="{Binding Message}"
TextWrapping="Wrap" />
<StackPanel
Name="ButtonStack"
@ -49,4 +51,4 @@
Orientation="Horizontal"
Spacing="10" />
</Grid>
</Window>
</Window>

View File

@ -4,7 +4,9 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views="using:Ryujinx.Ava.UI.Controls"
Width="400"
x:DataType="views:SwkbdAppletDialog"
mc:Ignorable="d"
Focusable="True">
<Grid
@ -34,13 +36,13 @@
Grid.Row="1"
Grid.Column="1"
Margin="5"
Text="{ReflectionBinding MainText}"
Text="{Binding MainText}"
TextWrapping="Wrap" />
<TextBlock
Grid.Row="2"
Grid.Column="1"
Margin="5"
Text="{ReflectionBinding SecondaryText}"
Text="{Binding SecondaryText}"
TextWrapping="Wrap" />
<TextBox
Name="Input"
@ -50,7 +52,7 @@
VerticalAlignment="Center"
Focusable="True"
KeyUp="Message_KeyUp"
Text="{ReflectionBinding Message}"
Text="{Binding Message}"
TextInput="Message_TextInput"
TextWrapping="Wrap"
UseFloatingWatermark="True" />

View File

@ -46,7 +46,7 @@
<Setter Property="CornerRadius" Value="4" />
</Style>
<Style Selector="ListBoxItem:selected /template/ Rectangle#SelectionIndicator">
<Setter Property="MinHeight" Value="{ReflectionBinding $parent[UserControl].DataContext.GridItemSelectorSize}" />
<Setter Property="MinHeight" Value="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).GridItemSelectorSize}" />
</Style>
</ListBox.Styles>
<ListBox.ItemTemplate>
@ -56,10 +56,10 @@
Margin="10"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Classes.huge="{ReflectionBinding $parent[UserControl].DataContext.IsGridHuge}"
Classes.large="{ReflectionBinding $parent[UserControl].DataContext.IsGridLarge}"
Classes.normal="{ReflectionBinding $parent[UserControl].DataContext.IsGridMedium}"
Classes.small="{ReflectionBinding $parent[UserControl].DataContext.IsGridSmall}"
Classes.huge="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridHuge}"
Classes.large="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridLarge}"
Classes.normal="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridMedium}"
Classes.small="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridSmall}"
ClipToBounds="True"
CornerRadius="4">
<Grid>
@ -78,7 +78,7 @@
Margin="0,10,0,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
IsVisible="{ReflectionBinding $parent[UserControl].DataContext.ShowNames}">
IsVisible="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).ShowNames}">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
@ -101,4 +101,4 @@
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</UserControl>
</UserControl>

View File

@ -42,7 +42,7 @@
</ListBox.ItemsPanel>
<ListBox.Styles>
<Style Selector="ListBoxItem:selected /template/ Rectangle#SelectionIndicator">
<Setter Property="MinHeight" Value="{ReflectionBinding $parent[UserControl].DataContext.ListItemSelectorSize}" />
<Setter Property="MinHeight" Value="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).ListItemSelectorSize}" />
</Style>
</ListBox.Styles>
<ListBox.ItemTemplate>
@ -67,10 +67,10 @@
Grid.RowSpan="3"
Grid.Column="0"
Margin="0"
Classes.huge="{ReflectionBinding $parent[UserControl].DataContext.IsGridHuge}"
Classes.large="{ReflectionBinding $parent[UserControl].DataContext.IsGridLarge}"
Classes.normal="{ReflectionBinding $parent[UserControl].DataContext.IsGridMedium}"
Classes.small="{ReflectionBinding $parent[UserControl].DataContext.IsGridSmall}"
Classes.huge="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridHuge}"
Classes.large="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridLarge}"
Classes.normal="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridMedium}"
Classes.small="{Binding $parent[UserControl].((viewModels:MainWindowViewModel)DataContext).IsGridSmall}"
Source="{Binding Icon, Converter={StaticResource ByteImage}}" />
<Border
Grid.Column="2"
@ -157,4 +157,4 @@
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</UserControl>
</UserControl>

View File

@ -11,6 +11,7 @@
Height="500"
MinWidth="500"
MinHeight="500"
x:DataType="window:CheatWindow"
WindowStartupLocation="CenterOwner"
mc:Ignorable="d"
Focusable="True">
@ -40,7 +41,7 @@
HorizontalAlignment="Center"
VerticalAlignment="Center"
LineHeight="18"
Text="{ReflectionBinding Heading}"
Text="{Binding Heading}"
TextAlignment="Center"
TextWrapping="Wrap" />
<TextBlock
@ -61,7 +62,7 @@
MinWidth="160"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="{ReflectionBinding BuildId}"
Text="{Binding BuildId}"
IsReadOnly="True" />
<Border
Grid.Row="3"
@ -77,7 +78,7 @@
MinHeight="300"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ItemsSource="{ReflectionBinding LoadedCheats}">
ItemsSource="{Binding LoadedCheats}">
<TreeView.Styles>
<Styles>
<Style Selector="TreeViewItem:empty /template/ ItemsPresenter">
@ -120,18 +121,18 @@
Name="SaveButton"
MinWidth="90"
Margin="5"
Command="{ReflectionBinding Save}"
IsVisible="{ReflectionBinding !NoCheatsFound}">
Command="{Binding Save}"
IsVisible="{Binding !NoCheatsFound}">
<TextBlock Text="{locale:Locale SettingsButtonSave}" />
</Button>
<Button
Name="CancelButton"
MinWidth="90"
Margin="5"
Command="{ReflectionBinding Close}">
Command="{Binding Close}">
<TextBlock Text="{locale:Locale InputDialogCancel}" />
</Button>
</DockPanel>
</DockPanel>
</Grid>
</window:StyleableWindow>
</window:StyleableWindow>

View File

@ -17,7 +17,7 @@ namespace Ryujinx.Ava.UI.Windows
private readonly string _enabledCheatsPath;
public bool NoCheatsFound { get; }
private AvaloniaList<CheatsList> LoadedCheats { get; }
public AvaloniaList<CheatsList> LoadedCheats { get; }
public string Heading { get; }
public string BuildId { get; }

View File

@ -39,14 +39,14 @@
Name="EnableAllButton"
MinWidth="90"
Margin="5"
Command="{ReflectionBinding EnableAll}">
Command="{Binding EnableAll}">
<TextBlock Text="{locale:Locale DlcManagerEnableAllButton}" />
</Button>
<Button
Name="DisableAllButton"
MinWidth="90"
Margin="5"
Command="{ReflectionBinding DisableAll}">
Command="{Binding DisableAll}">
<TextBlock Text="{locale:Locale DlcManagerDisableAllButton}" />
</Button>
</StackPanel>
@ -157,14 +157,14 @@
Name="AddButton"
MinWidth="90"
Margin="5"
Command="{ReflectionBinding Add}">
Command="{Binding Add}">
<TextBlock Text="{locale:Locale SettingsTabGeneralAdd}" />
</Button>
<Button
Name="RemoveAllButton"
MinWidth="90"
Margin="5"
Command="{ReflectionBinding RemoveAll}">
Command="{Binding RemoveAll}">
<TextBlock Text="{locale:Locale DlcManagerRemoveAllButton}" />
</Button>
</StackPanel>
@ -189,4 +189,4 @@
</StackPanel>
</Panel>
</Grid>
</UserControl>
</UserControl>

View File

@ -15,14 +15,6 @@ namespace Ryujinx.Graphics.GAL
BufferImage,
}
public enum ResourceAccess : byte
{
None = 0,
Read = 1,
Write = 2,
ReadWrite = Read | Write,
}
[Flags]
public enum ResourceStages : byte
{
@ -81,19 +73,17 @@ namespace Ryujinx.Graphics.GAL
public int Binding { get; }
public ResourceType Type { get; }
public ResourceStages Stages { get; }
public ResourceAccess Access { get; }
public ResourceUsage(int binding, ResourceType type, ResourceStages stages, ResourceAccess access)
public ResourceUsage(int binding, ResourceType type, ResourceStages stages)
{
Binding = binding;
Type = type;
Stages = stages;
Access = access;
}
public override int GetHashCode()
{
return HashCode.Combine(Binding, Type, Stages, Access);
return HashCode.Combine(Binding, Type, Stages);
}
public override bool Equals(object obj)
@ -103,7 +93,7 @@ namespace Ryujinx.Graphics.GAL
public bool Equals(ResourceUsage other)
{
return Binding == other.Binding && Type == other.Type && Stages == other.Stages && Access == other.Access;
return Binding == other.Binding && Type == other.Type && Stages == other.Stages;
}
public static bool operator ==(ResourceUsage left, ResourceUsage right)

View File

@ -490,10 +490,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
/// </summary>
/// <param name="offset">Offset of the range</param>
/// <param name="size">Size of the range in bytes</param>
/// <param name="write">Indicates if the buffer contents will be modified</param>
/// <returns>Range</returns>
public BufferRange GetVertexDataBufferRange(int offset, int size)
public BufferRange GetVertexDataBufferRange(int offset, int size, bool write)
{
return new BufferRange(_vertexDataBuffer.Handle, offset, size);
return new BufferRange(_vertexDataBuffer.Handle, offset, size, write);
}
/// <summary>
@ -501,10 +502,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
/// </summary>
/// <param name="offset">Offset of the range</param>
/// <param name="size">Size of the range in bytes</param>
/// <param name="write">Indicates if the buffer contents will be modified</param>
/// <returns>Range</returns>
public BufferRange GetGeometryVertexDataBufferRange(int offset, int size)
public BufferRange GetGeometryVertexDataBufferRange(int offset, int size, bool write)
{
return new BufferRange(_geometryVertexDataBuffer.Handle, offset, size);
return new BufferRange(_geometryVertexDataBuffer.Handle, offset, size, write);
}
/// <summary>
@ -512,10 +514,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
/// </summary>
/// <param name="offset">Offset of the range</param>
/// <param name="size">Size of the range in bytes</param>
/// <param name="write">Indicates if the buffer contents will be modified</param>
/// <returns>Range</returns>
public BufferRange GetGeometryIndexDataBufferRange(int offset, int size)
public BufferRange GetGeometryIndexDataBufferRange(int offset, int size, bool write)
{
return new BufferRange(_geometryIndexDataBuffer.Handle, offset, size);
return new BufferRange(_geometryIndexDataBuffer.Handle, offset, size, write);
}
/// <summary>

View File

@ -202,7 +202,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
_context.Renderer.Pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(vertexInfoBinding, vertexInfoRange) });
int vertexDataBinding = _vertexAsCompute.Reservations.VertexOutputStorageBufferBinding;
BufferRange vertexDataRange = _vacContext.GetVertexDataBufferRange(_vertexDataOffset, _vertexDataSize);
BufferRange vertexDataRange = _vacContext.GetVertexDataBufferRange(_vertexDataOffset, _vertexDataSize, write: true);
_context.Renderer.Pipeline.SetStorageBuffers(stackalloc[] { new BufferAssignment(vertexDataBinding, vertexDataRange) });
_vacContext.VertexInfoBufferUpdater.Commit();
@ -245,9 +245,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
int geometryVbBinding = _geometryAsCompute.Reservations.GeometryVertexOutputStorageBufferBinding;
int geometryIbBinding = _geometryAsCompute.Reservations.GeometryIndexOutputStorageBufferBinding;
BufferRange vertexDataRange = _vacContext.GetVertexDataBufferRange(_vertexDataOffset, _vertexDataSize);
BufferRange vertexBuffer = _vacContext.GetGeometryVertexDataBufferRange(_geometryVertexDataOffset, _geometryVertexDataSize);
BufferRange indexBuffer = _vacContext.GetGeometryIndexDataBufferRange(_geometryIndexDataOffset, _geometryIndexDataSize);
BufferRange vertexDataRange = _vacContext.GetVertexDataBufferRange(_vertexDataOffset, _vertexDataSize, write: false);
BufferRange vertexBuffer = _vacContext.GetGeometryVertexDataBufferRange(_geometryVertexDataOffset, _geometryVertexDataSize, write: true);
BufferRange indexBuffer = _vacContext.GetGeometryIndexDataBufferRange(_geometryIndexDataOffset, _geometryIndexDataSize, write: true);
_context.Renderer.Pipeline.SetStorageBuffers(stackalloc[]
{
@ -293,8 +293,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
if (_geometryAsCompute != null)
{
BufferRange vertexBuffer = _vacContext.GetGeometryVertexDataBufferRange(_geometryVertexDataOffset, _geometryVertexDataSize);
BufferRange indexBuffer = _vacContext.GetGeometryIndexDataBufferRange(_geometryIndexDataOffset, _geometryIndexDataSize);
BufferRange vertexBuffer = _vacContext.GetGeometryVertexDataBufferRange(_geometryVertexDataOffset, _geometryVertexDataSize, write: false);
BufferRange indexBuffer = _vacContext.GetGeometryIndexDataBufferRange(_geometryIndexDataOffset, _geometryIndexDataSize, write: false);
_context.Renderer.Pipeline.SetProgram(_vertexPassthroughProgram);
_context.Renderer.Pipeline.SetIndexBuffer(indexBuffer, IndexType.UInt);
@ -310,7 +310,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
}
else
{
BufferRange vertexDataRange = _vacContext.GetVertexDataBufferRange(_vertexDataOffset, _vertexDataSize);
BufferRange vertexDataRange = _vacContext.GetVertexDataBufferRange(_vertexDataOffset, _vertexDataSize, write: false);
_context.Renderer.Pipeline.SetProgram(_vertexPassthroughProgram);
_context.Renderer.Pipeline.SetStorageBuffers(stackalloc[] { new BufferAssignment(vertexDataBinding, vertexDataRange) });

View File

@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
private const ushort FileFormatVersionMajor = 1;
private const ushort FileFormatVersionMinor = 2;
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
private const uint CodeGenVersion = 5551;
private const uint CodeGenVersion = 5682;
private const string SharedTocFileName = "shared.toc";
private const string SharedDataFileName = "shared.data";

View File

@ -61,7 +61,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
}
AddDescriptor(SupportBufferStages, ResourceType.UniformBuffer, UniformSetIndex, 0, 1);
AddUsage(SupportBufferStages, ResourceType.UniformBuffer, ResourceAccess.Read, UniformSetIndex, 0, 1);
AddUsage(SupportBufferStages, ResourceType.UniformBuffer, UniformSetIndex, 0, 1);
ResourceReservationCounts rrc = new(!context.Capabilities.SupportsTransformFeedback && tfEnabled, vertexAsCompute);
@ -73,16 +73,16 @@ namespace Ryujinx.Graphics.Gpu.Shader
// TODO: Handle that better? Maybe we should only set the binding that are really needed on each shader.
ResourceStages stages = vertexAsCompute ? ResourceStages.Compute | ResourceStages.Vertex : VtgStages;
PopulateDescriptorAndUsages(stages, ResourceType.UniformBuffer, ResourceAccess.Read, UniformSetIndex, 1, rrc.ReservedConstantBuffers - 1);
PopulateDescriptorAndUsages(stages, ResourceType.StorageBuffer, ResourceAccess.ReadWrite, StorageSetIndex, 0, rrc.ReservedStorageBuffers);
PopulateDescriptorAndUsages(stages, ResourceType.BufferTexture, ResourceAccess.Read, TextureSetIndex, 0, rrc.ReservedTextures);
PopulateDescriptorAndUsages(stages, ResourceType.BufferImage, ResourceAccess.ReadWrite, ImageSetIndex, 0, rrc.ReservedImages);
PopulateDescriptorAndUsages(stages, ResourceType.UniformBuffer, UniformSetIndex, 1, rrc.ReservedConstantBuffers - 1);
PopulateDescriptorAndUsages(stages, ResourceType.StorageBuffer, StorageSetIndex, 0, rrc.ReservedStorageBuffers);
PopulateDescriptorAndUsages(stages, ResourceType.BufferTexture, TextureSetIndex, 0, rrc.ReservedTextures);
PopulateDescriptorAndUsages(stages, ResourceType.BufferImage, ImageSetIndex, 0, rrc.ReservedImages);
}
private void PopulateDescriptorAndUsages(ResourceStages stages, ResourceType type, ResourceAccess access, int setIndex, int start, int count)
private void PopulateDescriptorAndUsages(ResourceStages stages, ResourceType type, int setIndex, int start, int count)
{
AddDescriptor(stages, type, setIndex, start, count);
AddUsage(stages, type, access, setIndex, start, count);
AddUsage(stages, type, setIndex, start, count);
}
/// <summary>
@ -174,15 +174,14 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// </summary>
/// <param name="stages">Shader stages where the resource is used</param>
/// <param name="type">Type of the resource</param>
/// <param name="access">How the resource is accessed by the shader stages where it is used</param>
/// <param name="setIndex">Descriptor set number where the resource will be bound</param>
/// <param name="binding">Binding number where the resource will be bound</param>
/// <param name="count">Number of resources bound at the binding location</param>
private void AddUsage(ResourceStages stages, ResourceType type, ResourceAccess access, int setIndex, int binding, int count)
private void AddUsage(ResourceStages stages, ResourceType type, int setIndex, int binding, int count)
{
for (int index = 0; index < count; index++)
{
_resourceUsages[setIndex].Add(new ResourceUsage(binding + index, type, stages, access));
_resourceUsages[setIndex].Add(new ResourceUsage(binding + index, type, stages));
}
}
@ -200,8 +199,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
_resourceUsages[setIndex].Add(new ResourceUsage(
buffer.Binding,
isStorage ? ResourceType.StorageBuffer : ResourceType.UniformBuffer,
stages,
buffer.Flags.HasFlag(BufferUsageFlags.Write) ? ResourceAccess.ReadWrite : ResourceAccess.Read));
stages));
}
}
@ -225,8 +223,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
_resourceUsages[setIndex].Add(new ResourceUsage(
texture.Binding,
type,
stages,
texture.Flags.HasFlag(TextureUsageFlags.ImageStore) ? ResourceAccess.ReadWrite : ResourceAccess.Read));
stages));
}
}

View File

@ -89,6 +89,16 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
context.AddCapability(Capability.DrawParameters);
}
if (context.Definitions.Stage != ShaderStage.Fragment &&
context.Definitions.Stage != ShaderStage.Geometry &&
context.Definitions.Stage != ShaderStage.Compute &&
(context.Info.IoDefinitions.Contains(new IoDefinition(StorageKind.Output, IoVariable.Layer)) ||
context.Info.IoDefinitions.Contains(new IoDefinition(StorageKind.Output, IoVariable.ViewportIndex))))
{
context.AddExtension("SPV_EXT_shader_viewport_index_layer");
context.AddCapability(Capability.ShaderViewportIndexLayerEXT);
}
if (context.Info.IoDefinitions.Contains(new IoDefinition(StorageKind.Output, IoVariable.ViewportMask)))
{
context.AddExtension("SPV_NV_viewport_array2");
@ -277,14 +287,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
localSizeZ);
}
if (context.Definitions.Stage != ShaderStage.Fragment &&
context.Definitions.Stage != ShaderStage.Geometry &&
context.Definitions.Stage != ShaderStage.Compute &&
context.Info.IoDefinitions.Contains(new IoDefinition(StorageKind.Output, IoVariable.Layer)))
{
context.AddCapability(Capability.ShaderLayer);
}
if (context.Definitions.TransformFeedbackEnabled && context.Definitions.LastInVertexPipeline)
{
context.AddExecutionMode(spvFunc, ExecutionMode.Xfb);

View File

@ -1126,7 +1126,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
// so we want to get the byte offset back, since each one of those word
// offsets are a new "local variable" which will not match.
if (operation.GetSource(0).AsgOp is Operation shiftRightOp &&
if (operation.GetSource(1).AsgOp is Operation shiftRightOp &&
shiftRightOp.Inst == Instruction.ShiftRightU32 &&
shiftRightOp.GetSource(1).Type == OperandType.Constant &&
shiftRightOp.GetSource(1).Value == 2)
@ -1158,9 +1158,11 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
private static bool TryGetLocalMemoryOffset(Operation operation, out int constOffset)
{
if (operation.GetSource(0).Type == OperandType.Constant)
Operand offset = operation.GetSource(1);
if (offset.Type == OperandType.Constant)
{
constOffset = operation.GetSource(0).Value;
constOffset = offset.Value;
return true;
}

View File

@ -576,6 +576,11 @@ namespace Ryujinx.Graphics.Shader.Translation
int outputAttributesMask = AttributeUsage.UsedOutputAttributes;
int layerOutputAttr = LayerOutputAttribute;
if (LayerOutputWritten)
{
outputAttributesMask |= 1 << ((layerOutputAttr - AttributeConsts.UserAttributeBase) / 16);
}
OutputTopology outputTopology;
int maxOutputVertices;

View File

@ -257,14 +257,22 @@ namespace Ryujinx.Graphics.Vulkan
if (realIndex != -1)
{
_colors[realIndex].Storage?.InsertReadToWriteBarrier(cbs, AccessFlags.ColorAttachmentWriteBit, PipelineStageFlags.ColorAttachmentOutputBit);
_colors[realIndex].Storage?.InsertReadToWriteBarrier(
cbs,
AccessFlags.ColorAttachmentWriteBit,
PipelineStageFlags.ColorAttachmentOutputBit,
insideRenderPass: true);
}
}
}
public void InsertClearBarrierDS(CommandBufferScoped cbs)
{
_depthStencil?.Storage?.InsertReadToWriteBarrier(cbs, AccessFlags.DepthStencilAttachmentWriteBit, PipelineStageFlags.LateFragmentTestsBit);
_depthStencil?.Storage?.InsertReadToWriteBarrier(
cbs,
AccessFlags.DepthStencilAttachmentWriteBit,
PipelineStageFlags.LateFragmentTestsBit,
insideRenderPass: true);
}
}
}

View File

@ -41,6 +41,7 @@ namespace Ryujinx.Graphics.Vulkan
public readonly bool SupportsPreciseOcclusionQueries;
public readonly bool SupportsPipelineStatisticsQuery;
public readonly bool SupportsGeometryShader;
public readonly bool SupportsTessellationShader;
public readonly bool SupportsViewportArray2;
public readonly bool SupportsHostImportedMemory;
public readonly bool SupportsDepthClipControl;
@ -77,6 +78,7 @@ namespace Ryujinx.Graphics.Vulkan
bool supportsPreciseOcclusionQueries,
bool supportsPipelineStatisticsQuery,
bool supportsGeometryShader,
bool supportsTessellationShader,
bool supportsViewportArray2,
bool supportsHostImportedMemory,
bool supportsDepthClipControl,
@ -112,6 +114,7 @@ namespace Ryujinx.Graphics.Vulkan
SupportsPreciseOcclusionQueries = supportsPreciseOcclusionQueries;
SupportsPipelineStatisticsQuery = supportsPipelineStatisticsQuery;
SupportsGeometryShader = supportsGeometryShader;
SupportsTessellationShader = supportsTessellationShader;
SupportsViewportArray2 = supportsViewportArray2;
SupportsHostImportedMemory = supportsHostImportedMemory;
SupportsDepthClipControl = supportsDepthClipControl;

View File

@ -149,10 +149,22 @@ namespace Ryujinx.Graphics.Vulkan
DstAccessMask = AccessFlags.MemoryReadBit | AccessFlags.MemoryWriteBit,
};
PipelineStageFlags pipelineStageFlags = PipelineStageFlags.VertexShaderBit | PipelineStageFlags.FragmentShaderBit;
if (Gd.Capabilities.SupportsGeometryShader)
{
pipelineStageFlags |= PipelineStageFlags.GeometryShaderBit;
}
if (Gd.Capabilities.SupportsTessellationShader)
{
pipelineStageFlags |= PipelineStageFlags.TessellationControlShaderBit | PipelineStageFlags.TessellationEvaluationShaderBit;
}
Gd.Api.CmdPipelineBarrier(
CommandBuffer,
PipelineStageFlags.FragmentShaderBit,
PipelineStageFlags.FragmentShaderBit,
pipelineStageFlags,
pipelineStageFlags,
0,
1,
memoryBarrier,

View File

@ -9,8 +9,12 @@ namespace Ryujinx.Graphics.Vulkan
{
static class PipelineConverter
{
private const AccessFlags SubpassSrcAccessMask = AccessFlags.MemoryReadBit | AccessFlags.MemoryWriteBit | AccessFlags.ColorAttachmentWriteBit;
private const AccessFlags SubpassDstAccessMask = AccessFlags.MemoryReadBit | AccessFlags.MemoryWriteBit | AccessFlags.ShaderReadBit;
private const AccessFlags SubpassAccessMask =
AccessFlags.MemoryReadBit |
AccessFlags.MemoryWriteBit |
AccessFlags.ShaderReadBit |
AccessFlags.ColorAttachmentWriteBit |
AccessFlags.DepthStencilAttachmentWriteBit;
public static unsafe DisposableRenderPass ToRenderPass(this ProgramPipelineState state, VulkanRenderer gd, Device device)
{
@ -132,8 +136,8 @@ namespace Ryujinx.Graphics.Vulkan
0,
PipelineStageFlags.AllGraphicsBit,
PipelineStageFlags.AllGraphicsBit,
SubpassSrcAccessMask,
SubpassDstAccessMask,
SubpassAccessMask,
SubpassAccessMask,
0);
}
@ -146,8 +150,8 @@ namespace Ryujinx.Graphics.Vulkan
0,
PipelineStageFlags.AllGraphicsBit,
PipelineStageFlags.AllGraphicsBit,
SubpassSrcAccessMask,
SubpassDstAccessMask,
SubpassAccessMask,
SubpassAccessMask,
0);
}

View File

@ -146,7 +146,10 @@ namespace Ryujinx.Graphics.Vulkan
private void RecordScissor(Vk api, CommandBuffer commandBuffer)
{
api.CmdSetScissor(commandBuffer, 0, (uint)ScissorsCount, _scissors.AsSpan());
if (ScissorsCount != 0)
{
api.CmdSetScissor(commandBuffer, 0, (uint)ScissorsCount, _scissors.AsSpan());
}
}
private readonly void RecordStencilMasks(Vk api, CommandBuffer commandBuffer)

View File

@ -8,15 +8,13 @@ namespace Ryujinx.Graphics.Vulkan
public readonly int Count;
public readonly ResourceType Type;
public readonly ResourceStages Stages;
public readonly ResourceAccess Access;
public ResourceBindingSegment(int binding, int count, ResourceType type, ResourceStages stages, ResourceAccess access)
public ResourceBindingSegment(int binding, int count, ResourceType type, ResourceStages stages)
{
Binding = binding;
Count = count;
Type = type;
Stages = stages;
Access = access;
}
}
}

View File

@ -34,22 +34,12 @@ namespace Ryujinx.Graphics.Vulkan
_ => throw new ArgumentException($"Invalid resource type \"{type}\"."),
};
ResourceAccess access = IsReadOnlyType(type) ? ResourceAccess.Read : ResourceAccess.ReadWrite;
_resourceDescriptors[setIndex].Add(new ResourceDescriptor(binding, 1, type, stages));
_resourceUsages[setIndex].Add(new ResourceUsage(binding, type, stages, access));
_resourceUsages[setIndex].Add(new ResourceUsage(binding, type, stages));
return this;
}
private static bool IsReadOnlyType(ResourceType type)
{
return type == ResourceType.UniformBuffer ||
type == ResourceType.Sampler ||
type == ResourceType.TextureAndSampler ||
type == ResourceType.BufferTexture;
}
public ResourceLayout Build()
{
var descriptors = new ResourceDescriptorCollection[TotalSets];

View File

@ -162,8 +162,7 @@ namespace Ryujinx.Graphics.Vulkan
currentDescriptor.Binding,
currentCount,
currentDescriptor.Type,
currentDescriptor.Stages,
ResourceAccess.ReadWrite));
currentDescriptor.Stages));
}
currentDescriptor = descriptor;
@ -181,8 +180,7 @@ namespace Ryujinx.Graphics.Vulkan
currentDescriptor.Binding,
currentCount,
currentDescriptor.Type,
currentDescriptor.Stages,
ResourceAccess.ReadWrite));
currentDescriptor.Stages));
}
segments[setIndex] = currentSegments.ToArray();
@ -206,16 +204,9 @@ namespace Ryujinx.Graphics.Vulkan
{
ResourceUsage usage = setUsages[setIndex].Usages[index];
// If the resource is not accessed, we don't need to update it.
if (usage.Access == ResourceAccess.None)
{
continue;
}
if (currentUsage.Binding + currentCount != usage.Binding ||
currentUsage.Type != usage.Type ||
currentUsage.Stages != usage.Stages ||
currentUsage.Access != usage.Access)
currentUsage.Stages != usage.Stages)
{
if (currentCount != 0)
{
@ -223,8 +214,7 @@ namespace Ryujinx.Graphics.Vulkan
currentUsage.Binding,
currentCount,
currentUsage.Type,
currentUsage.Stages,
currentUsage.Access));
currentUsage.Stages));
}
currentUsage = usage;
@ -242,8 +232,7 @@ namespace Ryujinx.Graphics.Vulkan
currentUsage.Binding,
currentCount,
currentUsage.Type,
currentUsage.Stages,
currentUsage.Access));
currentUsage.Stages));
}
segments[setIndex] = currentSegments.ToArray();

View File

@ -78,7 +78,7 @@ namespace Ryujinx.Graphics.Vulkan
var sampleCountFlags = ConvertToSampleCountFlags(gd.Capabilities.SupportedSampleCounts, (uint)info.Samples);
var usage = GetImageUsage(info.Format, info.Target, gd.Capabilities.SupportsShaderStorageImageMultisample, forceStorage: true);
var usage = GetImageUsage(info.Format, info.Target, gd.Capabilities.SupportsShaderStorageImageMultisample);
var flags = ImageCreateFlags.CreateMutableFormatBit;
@ -291,7 +291,7 @@ namespace Ryujinx.Graphics.Vulkan
}
}
public static ImageUsageFlags GetImageUsage(Format format, Target target, bool supportsMsStorage, bool forceStorage = false)
public static ImageUsageFlags GetImageUsage(Format format, Target target, bool supportsMsStorage)
{
var usage = DefaultUsageFlags;
@ -304,7 +304,7 @@ namespace Ryujinx.Graphics.Vulkan
usage |= ImageUsageFlags.ColorAttachmentBit;
}
if (((forceStorage && !format.IsDepthOrStencil()) || format.IsImageCompatible()) && (supportsMsStorage || !target.IsMultisample()))
if (format.IsImageCompatible() && (supportsMsStorage || !target.IsMultisample()))
{
usage |= ImageUsageFlags.StorageBit;
}
@ -440,25 +440,27 @@ namespace Ryujinx.Graphics.Vulkan
_lastModificationStage = stage;
}
public void InsertReadToWriteBarrier(CommandBufferScoped cbs, AccessFlags dstAccessFlags, PipelineStageFlags dstStageFlags)
public void InsertReadToWriteBarrier(CommandBufferScoped cbs, AccessFlags dstAccessFlags, PipelineStageFlags dstStageFlags, bool insideRenderPass)
{
if (_lastReadAccess != AccessFlags.None)
{
ImageAspectFlags aspectFlags = Info.Format.ConvertAspectFlags();
var lastReadStage = _lastReadStage;
TextureView.InsertImageBarrier(
if (insideRenderPass)
{
// We can't have barrier from compute inside a render pass,
// as it is invalid to specify compute in the subpass dependency stage mask.
lastReadStage &= ~PipelineStageFlags.ComputeShaderBit;
}
if (lastReadStage != PipelineStageFlags.None)
{
TextureView.InsertMemoryBarrier(
_gd.Api,
cbs.CommandBuffer,
_imageAuto.Get(cbs).Value,
_lastReadAccess,
dstAccessFlags,
_lastReadStage,
dstStageFlags,
aspectFlags,
0,
0,
_info.GetLayers(),
_info.Levels);
lastReadStage,
dstStageFlags);
_lastReadAccess = AccessFlags.None;
_lastReadStage = PipelineStageFlags.None;
@ -472,21 +474,13 @@ namespace Ryujinx.Graphics.Vulkan
if (_lastModificationAccess != AccessFlags.None)
{
ImageAspectFlags aspectFlags = Info.Format.ConvertAspectFlags();
TextureView.InsertImageBarrier(
TextureView.InsertMemoryBarrier(
_gd.Api,
cbs.CommandBuffer,
_imageAuto.Get(cbs).Value,
_lastModificationAccess,
dstAccessFlags,
_lastModificationStage,
dstStageFlags,
aspectFlags,
0,
0,
_info.GetLayers(),
_info.Levels);
dstStageFlags);
_lastModificationAccess = AccessFlags.None;
}

View File

@ -435,6 +435,34 @@ namespace Ryujinx.Graphics.Vulkan
ImageAspectFlags.ColorBit);
}
public static unsafe void InsertMemoryBarrier(
Vk api,
CommandBuffer commandBuffer,
AccessFlags srcAccessMask,
AccessFlags dstAccessMask,
PipelineStageFlags srcStageMask,
PipelineStageFlags dstStageMask)
{
MemoryBarrier memoryBarrier = new()
{
SType = StructureType.MemoryBarrier,
SrcAccessMask = srcAccessMask,
DstAccessMask = dstAccessMask,
};
api.CmdPipelineBarrier(
commandBuffer,
srcStageMask,
dstStageMask,
DependencyFlags.None,
1,
memoryBarrier,
0,
null,
0,
null);
}
public static unsafe void InsertImageBarrier(
Vk api,
CommandBuffer commandBuffer,

View File

@ -327,6 +327,7 @@ namespace Ryujinx.Graphics.Vulkan
features2.Features.OcclusionQueryPrecise,
_physicalDevice.PhysicalDeviceFeatures.PipelineStatisticsQuery,
_physicalDevice.PhysicalDeviceFeatures.GeometryShader,
_physicalDevice.PhysicalDeviceFeatures.TessellationShader,
_physicalDevice.IsDeviceExtensionPresent("VK_NV_viewport_array2"),
_physicalDevice.IsDeviceExtensionPresent(ExtExternalMemoryHost.ExtensionName),
supportsDepthClipControl && featuresDepthClipControl.DepthClipControl,

View File

@ -22,8 +22,10 @@ namespace Ryujinx.Graphics.Vulkan
private Image[] _swapchainImages;
private Auto<DisposableImageView>[] _swapchainImageViews;
private Semaphore _imageAvailableSemaphore;
private Semaphore _renderFinishedSemaphore;
private Semaphore[] _imageAvailableSemaphores;
private Semaphore[] _renderFinishedSemaphores;
private int _frameIndex;
private int _width;
private int _height;
@ -48,14 +50,6 @@ namespace Ryujinx.Graphics.Vulkan
_surface = surface;
CreateSwapchain();
var semaphoreCreateInfo = new SemaphoreCreateInfo
{
SType = StructureType.SemaphoreCreateInfo,
};
gd.Api.CreateSemaphore(device, semaphoreCreateInfo, null, out _imageAvailableSemaphore).ThrowOnError();
gd.Api.CreateSemaphore(device, semaphoreCreateInfo, null, out _renderFinishedSemaphore).ThrowOnError();
}
private void RecreateSwapchain()
@ -69,7 +63,22 @@ namespace Ryujinx.Graphics.Vulkan
}
// Destroy old Swapchain.
_gd.Api.DeviceWaitIdle(_device);
unsafe
{
for (int i = 0; i < _imageAvailableSemaphores.Length; i++)
{
_gd.Api.DestroySemaphore(_device, _imageAvailableSemaphores[i], null);
}
for (int i = 0; i < _renderFinishedSemaphores.Length; i++)
{
_gd.Api.DestroySemaphore(_device, _renderFinishedSemaphores[i], null);
}
}
_gd.SwapchainApi.DestroySwapchain(_device, oldSwapchain, Span<AllocationCallbacks>.Empty);
CreateSwapchain();
@ -151,6 +160,25 @@ namespace Ryujinx.Graphics.Vulkan
{
_swapchainImageViews[i] = CreateSwapchainImageView(_swapchainImages[i], surfaceFormat.Format);
}
var semaphoreCreateInfo = new SemaphoreCreateInfo
{
SType = StructureType.SemaphoreCreateInfo,
};
_imageAvailableSemaphores = new Semaphore[imageCount];
for (int i = 0; i < _imageAvailableSemaphores.Length; i++)
{
_gd.Api.CreateSemaphore(_device, semaphoreCreateInfo, null, out _imageAvailableSemaphores[i]).ThrowOnError();
}
_renderFinishedSemaphores = new Semaphore[imageCount];
for (int i = 0; i < _renderFinishedSemaphores.Length; i++)
{
_gd.Api.CreateSemaphore(_device, semaphoreCreateInfo, null, out _renderFinishedSemaphores[i]).ThrowOnError();
}
}
private unsafe Auto<DisposableImageView> CreateSwapchainImageView(Image swapchainImage, VkFormat format)
@ -185,6 +213,7 @@ namespace Ryujinx.Graphics.Vulkan
{
return new SurfaceFormatKHR(VkFormat.B8G8R8A8Unorm, ColorSpaceKHR.PaceSrgbNonlinearKhr);
}
var formatToReturn = availableFormats[0];
if (colorSpacePassthroughEnabled)
{
@ -212,6 +241,7 @@ namespace Ryujinx.Graphics.Vulkan
}
}
}
return formatToReturn;
}
@ -265,6 +295,7 @@ namespace Ryujinx.Graphics.Vulkan
_gd.PipelineInternal.AutoFlush.Present();
uint nextImage = 0;
int semaphoreIndex = _frameIndex++ % _imageAvailableSemaphores.Length;
while (true)
{
@ -272,7 +303,7 @@ namespace Ryujinx.Graphics.Vulkan
_device,
_swapchain,
ulong.MaxValue,
_imageAvailableSemaphore,
_imageAvailableSemaphores[semaphoreIndex],
new Fence(),
ref nextImage);
@ -411,12 +442,12 @@ namespace Ryujinx.Graphics.Vulkan
_gd.CommandBufferPool.Return(
cbs,
stackalloc[] { _imageAvailableSemaphore },
stackalloc[] { _imageAvailableSemaphores[semaphoreIndex] },
stackalloc[] { PipelineStageFlags.ColorAttachmentOutputBit },
stackalloc[] { _renderFinishedSemaphore });
stackalloc[] { _renderFinishedSemaphores[semaphoreIndex] });
// TODO: Present queue.
var semaphore = _renderFinishedSemaphore;
var semaphore = _renderFinishedSemaphores[semaphoreIndex];
var swapchain = _swapchain;
Result result;
@ -593,14 +624,21 @@ namespace Ryujinx.Graphics.Vulkan
{
unsafe
{
_gd.Api.DestroySemaphore(_device, _renderFinishedSemaphore, null);
_gd.Api.DestroySemaphore(_device, _imageAvailableSemaphore, null);
for (int i = 0; i < _swapchainImageViews.Length; i++)
{
_swapchainImageViews[i].Dispose();
}
for (int i = 0; i < _imageAvailableSemaphores.Length; i++)
{
_gd.Api.DestroySemaphore(_device, _imageAvailableSemaphores[i], null);
}
for (int i = 0; i < _renderFinishedSemaphores.Length; i++)
{
_gd.Api.DestroySemaphore(_device, _renderFinishedSemaphores[i], null);
}
_gd.SwapchainApi.DestroySwapchain(_device, _swapchain, null);
}

View File

@ -68,15 +68,15 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
int ryujinxLogoSize = 32;
string ryujinxIconPath = "Ryujinx.HLE.HOS.Applets.SoftwareKeyboard.Resources.Logo_Ryujinx.png";
_ryujinxLogo = LoadResource(Assembly.GetExecutingAssembly(), ryujinxIconPath, ryujinxLogoSize, ryujinxLogoSize);
_ryujinxLogo = LoadResource(typeof(SoftwareKeyboardRendererBase).Assembly, ryujinxIconPath, ryujinxLogoSize, ryujinxLogoSize);
string padAcceptIconPath = "Ryujinx.HLE.HOS.Applets.SoftwareKeyboard.Resources.Icon_BtnA.png";
string padCancelIconPath = "Ryujinx.HLE.HOS.Applets.SoftwareKeyboard.Resources.Icon_BtnB.png";
string keyModeIconPath = "Ryujinx.HLE.HOS.Applets.SoftwareKeyboard.Resources.Icon_KeyF6.png";
_padAcceptIcon = LoadResource(Assembly.GetExecutingAssembly(), padAcceptIconPath, 0, 0);
_padCancelIcon = LoadResource(Assembly.GetExecutingAssembly(), padCancelIconPath, 0, 0);
_keyModeIcon = LoadResource(Assembly.GetExecutingAssembly(), keyModeIconPath, 0, 0);
_padAcceptIcon = LoadResource(typeof(SoftwareKeyboardRendererBase).Assembly, padAcceptIconPath, 0, 0);
_padCancelIcon = LoadResource(typeof(SoftwareKeyboardRendererBase).Assembly, padCancelIconPath, 0, 0);
_keyModeIcon = LoadResource(typeof(SoftwareKeyboardRendererBase).Assembly, keyModeIconPath, 0, 0);
Color panelColor = ToColor(uiTheme.DefaultBackgroundColor, 255);
Color panelTransparentColor = ToColor(uiTheme.DefaultBackgroundColor, 150);

View File

@ -5,6 +5,7 @@ using Ryujinx.HLE.HOS.Services.Settings.Types;
using Ryujinx.HLE.HOS.Services.Vi.RootService.ApplicationDisplayService;
using Ryujinx.HLE.HOS.SystemState;
using Ryujinx.Horizon.Common;
using Ryujinx.Horizon.Sdk.Lbl;
using System;
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
@ -15,7 +16,6 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
private readonly Apm.ManagerServer _apmManagerServer;
private readonly Apm.SystemManagerServer _apmSystemManagerServer;
private readonly Lbl.LblControllerServer _lblControllerServer;
private bool _vrModeEnabled;
#pragma warning disable CS0414, IDE0052 // Remove unread private member
@ -34,7 +34,6 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
_apmManagerServer = new Apm.ManagerServer(context);
_apmSystemManagerServer = new Apm.SystemManagerServer(context);
_lblControllerServer = new Lbl.LblControllerServer(context);
_acquiredSleepLockEvent = new KEvent(context.Device.System.KernelContext);
}
@ -215,13 +214,15 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
_vrModeEnabled = vrModeEnabled;
using var lblApi = new LblApi();
if (vrModeEnabled)
{
_lblControllerServer.EnableVrMode();
lblApi.EnableVrMode().AbortOnFailure();
}
else
{
_lblControllerServer.DisableVrMode();
lblApi.DisableVrMode().AbortOnFailure();
}
// TODO: It signals an internal event of ICommonStateGetter. We have to determine where this event is used.

View File

@ -23,14 +23,14 @@ namespace Ryujinx.HLE.HOS.Services
public IpcService(ServerBase server = null)
{
CmifCommands = Assembly.GetExecutingAssembly().GetTypes()
CmifCommands = typeof(IpcService).Assembly.GetTypes()
.Where(type => type == GetType())
.SelectMany(type => type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public))
.SelectMany(methodInfo => methodInfo.GetCustomAttributes(typeof(CommandCmifAttribute))
.Select(command => (((CommandCmifAttribute)command).Id, methodInfo)))
.ToDictionary(command => command.Id, command => command.methodInfo);
TipcCommands = Assembly.GetExecutingAssembly().GetTypes()
TipcCommands = typeof(IpcService).Assembly.GetTypes()
.Where(type => type == GetType())
.SelectMany(type => type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public))
.SelectMany(methodInfo => methodInfo.GetCustomAttributes(typeof(CommandTipcAttribute))

View File

@ -1,92 +0,0 @@
namespace Ryujinx.HLE.HOS.Services.Lbl
{
abstract class ILblController : IpcService
{
public ILblController(ServiceCtx context) { }
protected abstract void SetCurrentBrightnessSettingForVrMode(float currentBrightnessSettingForVrMode);
protected abstract float GetCurrentBrightnessSettingForVrMode();
internal abstract void EnableVrMode();
internal abstract void DisableVrMode();
protected abstract bool IsVrModeEnabled();
[CommandCmif(17)]
// SetBrightnessReflectionDelayLevel(float, float)
public ResultCode SetBrightnessReflectionDelayLevel(ServiceCtx context)
{
return ResultCode.Success;
}
[CommandCmif(18)]
// GetBrightnessReflectionDelayLevel(float) -> float
public ResultCode GetBrightnessReflectionDelayLevel(ServiceCtx context)
{
context.ResponseData.Write(0.0f);
return ResultCode.Success;
}
[CommandCmif(21)]
// SetCurrentAmbientLightSensorMapping(unknown<0xC>)
public ResultCode SetCurrentAmbientLightSensorMapping(ServiceCtx context)
{
return ResultCode.Success;
}
[CommandCmif(22)]
// GetCurrentAmbientLightSensorMapping() -> unknown<0xC>
public ResultCode GetCurrentAmbientLightSensorMapping(ServiceCtx context)
{
return ResultCode.Success;
}
[CommandCmif(24)] // 3.0.0+
// SetCurrentBrightnessSettingForVrMode(float)
public ResultCode SetCurrentBrightnessSettingForVrMode(ServiceCtx context)
{
float currentBrightnessSettingForVrMode = context.RequestData.ReadSingle();
SetCurrentBrightnessSettingForVrMode(currentBrightnessSettingForVrMode);
return ResultCode.Success;
}
[CommandCmif(25)] // 3.0.0+
// GetCurrentBrightnessSettingForVrMode() -> float
public ResultCode GetCurrentBrightnessSettingForVrMode(ServiceCtx context)
{
float currentBrightnessSettingForVrMode = GetCurrentBrightnessSettingForVrMode();
context.ResponseData.Write(currentBrightnessSettingForVrMode);
return ResultCode.Success;
}
[CommandCmif(26)] // 3.0.0+
// EnableVrMode()
public ResultCode EnableVrMode(ServiceCtx context)
{
EnableVrMode();
return ResultCode.Success;
}
[CommandCmif(27)] // 3.0.0+
// DisableVrMode()
public ResultCode DisableVrMode(ServiceCtx context)
{
DisableVrMode();
return ResultCode.Success;
}
[CommandCmif(28)] // 3.0.0+
// IsVrModeEnabled() -> bool
public ResultCode IsVrModeEnabled(ServiceCtx context)
{
context.ResponseData.Write(IsVrModeEnabled());
return ResultCode.Success;
}
}
}

View File

@ -1,54 +0,0 @@
namespace Ryujinx.HLE.HOS.Services.Lbl
{
[Service("lbl")]
class LblControllerServer : ILblController
{
private bool _vrModeEnabled;
private float _currentBrightnessSettingForVrMode;
public LblControllerServer(ServiceCtx context) : base(context) { }
protected override void SetCurrentBrightnessSettingForVrMode(float currentBrightnessSettingForVrMode)
{
if (float.IsNaN(currentBrightnessSettingForVrMode) || float.IsInfinity(currentBrightnessSettingForVrMode))
{
_currentBrightnessSettingForVrMode = 0.0f;
return;
}
_currentBrightnessSettingForVrMode = currentBrightnessSettingForVrMode;
}
protected override float GetCurrentBrightnessSettingForVrMode()
{
if (float.IsNaN(_currentBrightnessSettingForVrMode) || float.IsInfinity(_currentBrightnessSettingForVrMode))
{
return 0.0f;
}
return _currentBrightnessSettingForVrMode;
}
internal override void EnableVrMode()
{
_vrModeEnabled = true;
// NOTE: Service check _vrModeEnabled field value in a thread and then change the screen brightness.
// Since we don't support that. It's fine to do nothing.
}
internal override void DisableVrMode()
{
_vrModeEnabled = false;
// NOTE: Service check _vrModeEnabled field value in a thread and then change the screen brightness.
// Since we don't support that. It's fine to do nothing.
}
protected override bool IsVrModeEnabled()
{
return _vrModeEnabled;
}
}
}

View File

@ -6,6 +6,7 @@ using Ryujinx.HLE.HOS.Kernel;
using Ryujinx.HLE.HOS.Kernel.Ipc;
using Ryujinx.HLE.HOS.Kernel.Process;
using Ryujinx.HLE.HOS.Kernel.Threading;
using Ryujinx.Horizon;
using Ryujinx.Horizon.Common;
using System;
using System.Buffers;
@ -172,6 +173,13 @@ namespace Ryujinx.HLE.HOS.Services
_selfProcess = KernelStatic.GetCurrentProcess();
_selfThread = KernelStatic.GetCurrentThread();
HorizonStatic.Register(
default,
_context.Syscall,
_selfProcess.CpuMemory,
_selfThread.ThreadContext,
(int)_selfThread.ThreadContext.GetX(1));
if (SmObjectFactory != null)
{
_context.Syscall.ManageNamedPort(out int serverPortHandle, "sm:", 50);

View File

@ -28,7 +28,7 @@ namespace Ryujinx.HLE.HOS.Services.Sm
static IUserInterface()
{
_services = Assembly.GetExecutingAssembly().GetTypes()
_services = typeof(IUserInterface).Assembly.GetTypes()
.SelectMany(type => type.GetCustomAttributes(typeof(ServiceAttribute), true)
.Select(service => (((ServiceAttribute)service).Name, type)))
.ToDictionary(service => service.Name, service => service.type);

View File

@ -299,11 +299,21 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
{
try
{
LinuxError result = WinSockHelper.ValidateSocketOption(option, level, write: false);
if (result != LinuxError.SUCCESS)
{
Logger.Warning?.Print(LogClass.ServiceBsd, $"Invalid GetSockOpt Option: {option} Level: {level}");
return result;
}
if (!WinSockHelper.TryConvertSocketOption(option, level, out SocketOptionName optionName))
{
Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported GetSockOpt Option: {option} Level: {level}");
optionValue.Clear();
return LinuxError.EOPNOTSUPP;
return LinuxError.SUCCESS;
}
byte[] tempOptionValue = new byte[optionValue.Length];
@ -324,11 +334,20 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
{
try
{
LinuxError result = WinSockHelper.ValidateSocketOption(option, level, write: true);
if (result != LinuxError.SUCCESS)
{
Logger.Warning?.Print(LogClass.ServiceBsd, $"Invalid SetSockOpt Option: {option} Level: {level}");
return result;
}
if (!WinSockHelper.TryConvertSocketOption(option, level, out SocketOptionName optionName))
{
Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported SetSockOpt Option: {option} Level: {level}");
return LinuxError.EOPNOTSUPP;
return LinuxError.SUCCESS;
}
int value = optionValue.Length >= 4 ? MemoryMarshal.Read<int>(optionValue) : MemoryMarshal.Read<byte>(optionValue);

View File

@ -183,6 +183,104 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
{ BsdSocketOption.TcpKeepCnt, SocketOptionName.TcpKeepAliveRetryCount },
};
[Flags]
private enum OptionDir
{
Get = 1 << 0,
Set = 1 << 1,
GetSet = Get | Set,
}
private static readonly Dictionary<BsdSocketOption, OptionDir> _validSoSocketOptionMap = new()
{
{ BsdSocketOption.SoDebug, OptionDir.GetSet },
{ BsdSocketOption.SoAcceptConn, OptionDir.Get },
{ BsdSocketOption.SoReuseAddr, OptionDir.GetSet },
{ BsdSocketOption.SoKeepAlive, OptionDir.GetSet },
{ BsdSocketOption.SoDontRoute, OptionDir.GetSet },
{ BsdSocketOption.SoBroadcast, OptionDir.GetSet },
{ BsdSocketOption.SoUseLoopBack, OptionDir.GetSet },
{ BsdSocketOption.SoLinger, OptionDir.GetSet },
{ BsdSocketOption.SoOobInline, OptionDir.GetSet },
{ BsdSocketOption.SoReusePort, OptionDir.GetSet },
{ BsdSocketOption.SoTimestamp, OptionDir.GetSet },
{ BsdSocketOption.SoNoSigpipe, OptionDir.GetSet },
{ BsdSocketOption.SoAcceptFilter, OptionDir.GetSet },
{ BsdSocketOption.SoSndBuf, OptionDir.GetSet },
{ BsdSocketOption.SoRcvBuf, OptionDir.GetSet },
{ BsdSocketOption.SoSndLoWat, OptionDir.GetSet },
{ BsdSocketOption.SoRcvLoWat, OptionDir.GetSet },
{ BsdSocketOption.SoSndTimeo, OptionDir.GetSet },
{ BsdSocketOption.SoRcvTimeo, OptionDir.GetSet },
{ BsdSocketOption.SoError, OptionDir.Get },
{ BsdSocketOption.SoType, OptionDir.Get },
{ BsdSocketOption.SoLabel, OptionDir.Get },
{ BsdSocketOption.SoPeerLabel, OptionDir.Get },
{ BsdSocketOption.SoListenQLimit, OptionDir.Get },
{ BsdSocketOption.SoListenQLen, OptionDir.Get },
{ BsdSocketOption.SoListenIncQLen, OptionDir.Get },
{ BsdSocketOption.SoSetFib, OptionDir.Set },
{ BsdSocketOption.SoUserCookie, OptionDir.Set },
{ BsdSocketOption.SoProtocol, OptionDir.Get },
{ BsdSocketOption.SoBinTime, OptionDir.GetSet },
{ BsdSocketOption.SoNoOffload, OptionDir.Set },
{ BsdSocketOption.SoNoDdp, OptionDir.Set },
{ BsdSocketOption.SoReusePortLb, OptionDir.GetSet },
};
private static readonly Dictionary<BsdSocketOption, OptionDir> _validIpSocketOptionMap = new()
{
{ BsdSocketOption.IpOptions, OptionDir.GetSet },
{ BsdSocketOption.IpHdrIncl, OptionDir.GetSet },
{ BsdSocketOption.IpTos, OptionDir.GetSet },
{ BsdSocketOption.IpTtl, OptionDir.GetSet },
{ BsdSocketOption.IpRecvOpts, OptionDir.GetSet },
{ BsdSocketOption.IpRecvRetOpts, OptionDir.GetSet },
{ BsdSocketOption.IpRecvDstAddr, OptionDir.GetSet },
{ BsdSocketOption.IpRetOpts, OptionDir.GetSet },
{ BsdSocketOption.IpMulticastIf, OptionDir.GetSet },
{ BsdSocketOption.IpMulticastTtl, OptionDir.GetSet },
{ BsdSocketOption.IpMulticastLoop, OptionDir.GetSet },
{ BsdSocketOption.IpAddMembership, OptionDir.GetSet },
{ BsdSocketOption.IpDropMembership, OptionDir.GetSet },
{ BsdSocketOption.IpMulticastVif, OptionDir.GetSet },
{ BsdSocketOption.IpRsvpOn, OptionDir.GetSet },
{ BsdSocketOption.IpRsvpOff, OptionDir.GetSet },
{ BsdSocketOption.IpRsvpVifOn, OptionDir.GetSet },
{ BsdSocketOption.IpRsvpVifOff, OptionDir.GetSet },
{ BsdSocketOption.IpPortRange, OptionDir.GetSet },
{ BsdSocketOption.IpRecvIf, OptionDir.GetSet },
{ BsdSocketOption.IpIpsecPolicy, OptionDir.GetSet },
{ BsdSocketOption.IpOnesBcast, OptionDir.GetSet },
{ BsdSocketOption.IpBindany, OptionDir.GetSet },
{ BsdSocketOption.IpBindMulti, OptionDir.GetSet },
{ BsdSocketOption.IpRssListenBucket, OptionDir.GetSet },
{ BsdSocketOption.IpOrigDstAddr, OptionDir.GetSet },
{ BsdSocketOption.IpRecvTtl, OptionDir.GetSet },
{ BsdSocketOption.IpMinTtl, OptionDir.GetSet },
{ BsdSocketOption.IpDontFrag, OptionDir.GetSet },
{ BsdSocketOption.IpRecvTos, OptionDir.GetSet },
{ BsdSocketOption.IpAddSourceMembership, OptionDir.GetSet },
{ BsdSocketOption.IpDropSourceMembership, OptionDir.GetSet },
{ BsdSocketOption.IpBlockSource, OptionDir.GetSet },
{ BsdSocketOption.IpUnblockSource, OptionDir.GetSet },
};
private static readonly Dictionary<BsdSocketOption, OptionDir> _validTcpSocketOptionMap = new()
{
{ BsdSocketOption.TcpNoDelay, OptionDir.GetSet },
{ BsdSocketOption.TcpMaxSeg, OptionDir.GetSet },
{ BsdSocketOption.TcpNoPush, OptionDir.GetSet },
{ BsdSocketOption.TcpNoOpt, OptionDir.GetSet },
{ BsdSocketOption.TcpMd5Sig, OptionDir.GetSet },
{ BsdSocketOption.TcpInfo, OptionDir.GetSet },
{ BsdSocketOption.TcpCongestion, OptionDir.GetSet },
{ BsdSocketOption.TcpKeepInit, OptionDir.GetSet },
{ BsdSocketOption.TcpKeepIdle, OptionDir.GetSet },
{ BsdSocketOption.TcpKeepIntvl, OptionDir.GetSet },
{ BsdSocketOption.TcpKeepCnt, OptionDir.GetSet },
};
public static LinuxError ConvertError(WsaError errorCode)
{
if (OperatingSystem.IsMacOS())
@ -221,5 +319,29 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
return table.TryGetValue(option, out name);
}
public static LinuxError ValidateSocketOption(BsdSocketOption option, SocketOptionLevel level, bool write)
{
var table = level switch
{
SocketOptionLevel.Socket => _validSoSocketOptionMap,
SocketOptionLevel.IP => _validIpSocketOptionMap,
SocketOptionLevel.Tcp => _validTcpSocketOptionMap,
_ => null,
};
OptionDir dir = write ? OptionDir.Set : OptionDir.Get;
if (table == null || !table.TryGetValue(option, out OptionDir validDir))
{
return LinuxError.ENOPROTOOPT;
}
else if ((validDir & dir) != dir)
{
return LinuxError.EOPNOTSUPP;
}
return LinuxError.SUCCESS;
}
}
}

View File

@ -1,8 +0,0 @@
namespace Ryujinx.HLE.HOS.Services.Wlan
{
[Service("wlan:inf")]
class IInfraManager : IpcService
{
public IInfraManager(ServiceCtx context) { }
}
}

View File

@ -1,8 +0,0 @@
namespace Ryujinx.HLE.HOS.Services.Wlan
{
[Service("wlan:lga")]
class ILocalGetActionFrame : IpcService
{
public ILocalGetActionFrame(ServiceCtx context) { }
}
}

View File

@ -1,8 +0,0 @@
namespace Ryujinx.HLE.HOS.Services.Wlan
{
[Service("wlan:lg")]
class ILocalGetFrame : IpcService
{
public ILocalGetFrame(ServiceCtx context) { }
}
}

View File

@ -1,8 +0,0 @@
namespace Ryujinx.HLE.HOS.Services.Wlan
{
[Service("wlan:lcl")]
class ILocalManager : IpcService
{
public ILocalManager(ServiceCtx context) { }
}
}

View File

@ -1,8 +0,0 @@
namespace Ryujinx.HLE.HOS.Services.Wlan
{
[Service("wlan:sg")]
class ISocketGetFrame : IpcService
{
public ISocketGetFrame(ServiceCtx context) { }
}
}

View File

@ -1,8 +0,0 @@
namespace Ryujinx.HLE.HOS.Services.Wlan
{
[Service("wlan:soc")]
class ISocketManager : IpcService
{
public ISocketManager(ServiceCtx context) { }
}
}

View File

@ -1,8 +0,0 @@
namespace Ryujinx.HLE.HOS.Services.Wlan
{
[Service("wlan:dtc")] // 6.0.0+
class IUnknown1 : IpcService
{
public IUnknown1(ServiceCtx context) { }
}
}

View File

@ -17,7 +17,6 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using static SDL2.SDL;
@ -122,7 +121,7 @@ namespace Ryujinx.Headless.SDL2
private void SetWindowIcon()
{
Stream iconStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Ryujinx.Headless.SDL2.Ryujinx.bmp");
Stream iconStream = typeof(WindowBase).Assembly.GetManifestResourceStream("Ryujinx.Headless.SDL2.Ryujinx.bmp");
byte[] iconBytes = new byte[iconStream!.Length];
if (iconStream.Read(iconBytes, 0, iconBytes.Length) != iconBytes.Length)

View File

@ -6,8 +6,8 @@ namespace Ryujinx.Horizon.Bcat
{
internal class BcatIpcServer
{
private const int BcatMaxSessionsCount = 8;
private const int BcatTotalMaxSessionsCount = BcatMaxSessionsCount * 4;
private const int MaxSessionsCount = 8;
private const int TotalMaxSessionsCount = MaxSessionsCount * 4;
private const int PointerBufferSize = 0x400;
private const int MaxDomains = 64;
@ -17,7 +17,7 @@ namespace Ryujinx.Horizon.Bcat
private SmApi _sm;
private BcatServerManager _serverManager;
private static readonly ManagerOptions _bcatManagerOptions = new(PointerBufferSize, MaxDomains, MaxDomainObjects, false);
private static readonly ManagerOptions _managerOptions = new(PointerBufferSize, MaxDomains, MaxDomainObjects, false);
internal void Initialize()
{
@ -26,13 +26,13 @@ namespace Ryujinx.Horizon.Bcat
_sm = new SmApi();
_sm.Initialize().AbortOnFailure();
_serverManager = new BcatServerManager(allocator, _sm, MaxPortsCount, _bcatManagerOptions, BcatTotalMaxSessionsCount);
_serverManager = new BcatServerManager(allocator, _sm, MaxPortsCount, _managerOptions, TotalMaxSessionsCount);
#pragma warning disable IDE0055 // Disable formatting
_serverManager.RegisterServer((int)BcatPortIndex.Admin, ServiceName.Encode("bcat:a"), BcatMaxSessionsCount);
_serverManager.RegisterServer((int)BcatPortIndex.Manager, ServiceName.Encode("bcat:m"), BcatMaxSessionsCount);
_serverManager.RegisterServer((int)BcatPortIndex.User, ServiceName.Encode("bcat:u"), BcatMaxSessionsCount);
_serverManager.RegisterServer((int)BcatPortIndex.System, ServiceName.Encode("bcat:s"), BcatMaxSessionsCount);
_serverManager.RegisterServer((int)BcatPortIndex.Admin, ServiceName.Encode("bcat:a"), MaxSessionsCount);
_serverManager.RegisterServer((int)BcatPortIndex.Manager, ServiceName.Encode("bcat:m"), MaxSessionsCount);
_serverManager.RegisterServer((int)BcatPortIndex.User, ServiceName.Encode("bcat:u"), MaxSessionsCount);
_serverManager.RegisterServer((int)BcatPortIndex.System, ServiceName.Encode("bcat:s"), MaxSessionsCount);
#pragma warning restore IDE0055
}

View File

@ -4,7 +4,7 @@ using System;
namespace Ryujinx.Horizon
{
static class HorizonStatic
public static class HorizonStatic
{
[ThreadStatic]
private static HorizonOptions _options;

View File

@ -0,0 +1,130 @@
using Ryujinx.Horizon.Common;
using Ryujinx.Horizon.Sdk.Lbl;
using Ryujinx.Horizon.Sdk.Sf;
namespace Ryujinx.Horizon.Lbl.Ipc
{
partial class LblController : ILblController
{
private bool _vrModeEnabled;
private float _currentBrightnessSettingForVrMode;
[CmifCommand(17)]
public Result SetBrightnessReflectionDelayLevel(float unknown0, float unknown1)
{
// NOTE: Stubbed in system module.
return Result.Success;
}
[CmifCommand(18)]
public Result GetBrightnessReflectionDelayLevel(out float unknown1, float unknown0)
{
// NOTE: Stubbed in system module.
unknown1 = 0.0f;
return Result.Success;
}
[CmifCommand(19)]
public Result SetCurrentBrightnessMapping(float unknown0, float unknown1, float unknown2)
{
// NOTE: Stubbed in system module.
return Result.Success;
}
[CmifCommand(20)]
public Result GetCurrentBrightnessMapping(out float unknown0, out float unknown1, out float unknown2)
{
// NOTE: Stubbed in system module.
unknown0 = 0.0f;
unknown1 = 0.0f;
unknown2 = 0.0f;
return Result.Success;
}
[CmifCommand(21)]
public Result SetCurrentAmbientLightSensorMapping(float unknown0, float unknown1, float unknown2)
{
// NOTE: Stubbed in system module.
return Result.Success;
}
[CmifCommand(22)]
public Result GetCurrentAmbientLightSensorMapping(out float unknown0, out float unknown1, out float unknown2)
{
// NOTE: Stubbed in system module.
unknown0 = 0.0f;
unknown1 = 0.0f;
unknown2 = 0.0f;
return Result.Success;
}
[CmifCommand(24)]
public Result SetCurrentBrightnessSettingForVrMode(float currentBrightnessSettingForVrMode)
{
if (float.IsNaN(currentBrightnessSettingForVrMode) || float.IsInfinity(currentBrightnessSettingForVrMode))
{
_currentBrightnessSettingForVrMode = 0.0f;
}
else
{
_currentBrightnessSettingForVrMode = currentBrightnessSettingForVrMode;
}
return Result.Success;
}
[CmifCommand(25)]
public Result GetCurrentBrightnessSettingForVrMode(out float currentBrightnessSettingForVrMode)
{
if (float.IsNaN(_currentBrightnessSettingForVrMode) || float.IsInfinity(_currentBrightnessSettingForVrMode))
{
currentBrightnessSettingForVrMode = 0.0f;
}
else
{
currentBrightnessSettingForVrMode = _currentBrightnessSettingForVrMode;
}
return Result.Success;
}
[CmifCommand(26)]
public Result EnableVrMode()
{
_vrModeEnabled = true;
// NOTE: The service checks _vrModeEnabled field value in a thread and then changes the screen brightness.
// Since we don't support that, it's fine to do nothing.
return Result.Success;
}
[CmifCommand(27)]
public Result DisableVrMode()
{
_vrModeEnabled = false;
// NOTE: The service checks _vrModeEnabled field value in a thread and then changes the screen brightness.
// Since we don't support that, it's fine to do nothing.
return Result.Success;
}
[CmifCommand(28)]
public Result IsVrModeEnabled(out bool vrModeEnabled)
{
vrModeEnabled = _vrModeEnabled;
return Result.Success;
}
}
}

View File

@ -0,0 +1,43 @@
using Ryujinx.Horizon.Lbl.Ipc;
using Ryujinx.Horizon.Sdk.Sf.Hipc;
using Ryujinx.Horizon.Sdk.Sm;
namespace Ryujinx.Horizon.Lbl
{
class LblIpcServer
{
private const int MaxSessionsCount = 5;
private const int PointerBufferSize = 0;
private const int MaxDomains = 0;
private const int MaxDomainObjects = 0;
private const int MaxPortsCount = 1;
private static readonly ManagerOptions _managerOptions = new(PointerBufferSize, MaxDomains, MaxDomainObjects, false);
private SmApi _sm;
private ServerManager _serverManager;
public void Initialize()
{
HeapAllocator allocator = new();
_sm = new SmApi();
_sm.Initialize().AbortOnFailure();
_serverManager = new ServerManager(allocator, _sm, MaxPortsCount, _managerOptions, MaxSessionsCount);
_serverManager.RegisterObjectForServer(new LblController(), ServiceName.Encode("lbl"), MaxSessionsCount);
}
public void ServiceRequests()
{
_serverManager.ServiceRequests();
}
public void Shutdown()
{
_serverManager.Dispose();
}
}
}

View File

@ -0,0 +1,17 @@
namespace Ryujinx.Horizon.Lbl
{
class LblMain : IService
{
public static void Main(ServiceTable serviceTable)
{
LblIpcServer ipcServer = new();
ipcServer.Initialize();
serviceTable.SignalServiceReady();
ipcServer.ServiceRequests();
ipcServer.Shutdown();
}
}
}

View File

@ -6,14 +6,14 @@ namespace Ryujinx.Horizon.LogManager
{
class LmIpcServer
{
private const int LogMaxSessionsCount = 42;
private const int MaxSessionsCount = 42;
private const int PointerBufferSize = 0x400;
private const int MaxDomains = 31;
private const int MaxDomainObjects = 61;
private const int MaxPortsCount = 1;
private static readonly ManagerOptions _logManagerOptions = new(PointerBufferSize, MaxDomains, MaxDomainObjects, false);
private static readonly ManagerOptions _managerOptions = new(PointerBufferSize, MaxDomains, MaxDomainObjects, false);
private SmApi _sm;
private ServerManager _serverManager;
@ -25,9 +25,9 @@ namespace Ryujinx.Horizon.LogManager
_sm = new SmApi();
_sm.Initialize().AbortOnFailure();
_serverManager = new ServerManager(allocator, _sm, MaxPortsCount, _logManagerOptions, LogMaxSessionsCount);
_serverManager = new ServerManager(allocator, _sm, MaxPortsCount, _managerOptions, MaxSessionsCount);
_serverManager.RegisterObjectForServer(new LogService(), ServiceName.Encode("lm"), LogMaxSessionsCount);
_serverManager.RegisterObjectForServer(new LogService(), ServiceName.Encode("lm"), MaxSessionsCount);
}
public void ServiceRequests()

View File

@ -6,14 +6,14 @@ namespace Ryujinx.Horizon.MmNv
{
class MmNvIpcServer
{
private const int MmNvMaxSessionsCount = 9;
private const int MaxSessionsCount = 40;
private const int PointerBufferSize = 0;
private const int MaxDomains = 0;
private const int MaxDomainObjects = 0;
private const int MaxPortsCount = 1;
private static readonly ManagerOptions _mmNvOptions = new(PointerBufferSize, MaxDomains, MaxDomainObjects, false);
private static readonly ManagerOptions _managerOptions = new(PointerBufferSize, MaxDomains, MaxDomainObjects, false);
private SmApi _sm;
private ServerManager _serverManager;
@ -25,9 +25,9 @@ namespace Ryujinx.Horizon.MmNv
_sm = new SmApi();
_sm.Initialize().AbortOnFailure();
_serverManager = new ServerManager(allocator, _sm, MaxPortsCount, _mmNvOptions, MmNvMaxSessionsCount);
_serverManager = new ServerManager(allocator, _sm, MaxPortsCount, _managerOptions, MaxSessionsCount);
_serverManager.RegisterObjectForServer(new Request(), ServiceName.Encode("mm:u"), MmNvMaxSessionsCount);
_serverManager.RegisterObjectForServer(new Request(), ServiceName.Encode("mm:u"), MaxSessionsCount);
}
public void ServiceRequests()

View File

@ -6,15 +6,15 @@ namespace Ryujinx.Horizon.Prepo
{
class PrepoIpcServer
{
private const int PrepoMaxSessionsCount = 12;
private const int PrepoTotalMaxSessionsCount = PrepoMaxSessionsCount * 6;
private const int MaxSessionsCount = 12;
private const int TotalMaxSessionsCount = MaxSessionsCount * 6;
private const int PointerBufferSize = 0x80;
private const int MaxDomains = 64;
private const int MaxDomainObjects = 16;
private const int MaxPortsCount = 6;
private static readonly ManagerOptions _prepoManagerOptions = new(PointerBufferSize, MaxDomains, MaxDomainObjects, false);
private static readonly ManagerOptions _managerOptions = new(PointerBufferSize, MaxDomains, MaxDomainObjects, false);
private SmApi _sm;
private PrepoServerManager _serverManager;
@ -26,15 +26,15 @@ namespace Ryujinx.Horizon.Prepo
_sm = new SmApi();
_sm.Initialize().AbortOnFailure();
_serverManager = new PrepoServerManager(allocator, _sm, MaxPortsCount, _prepoManagerOptions, PrepoTotalMaxSessionsCount);
_serverManager = new PrepoServerManager(allocator, _sm, MaxPortsCount, _managerOptions, TotalMaxSessionsCount);
#pragma warning disable IDE0055 // Disable formatting
_serverManager.RegisterServer((int)PrepoPortIndex.Admin, ServiceName.Encode("prepo:a"), PrepoMaxSessionsCount); // 1.0.0-5.1.0
_serverManager.RegisterServer((int)PrepoPortIndex.Admin2, ServiceName.Encode("prepo:a2"), PrepoMaxSessionsCount); // 6.0.0+
_serverManager.RegisterServer((int)PrepoPortIndex.Manager, ServiceName.Encode("prepo:m"), PrepoMaxSessionsCount);
_serverManager.RegisterServer((int)PrepoPortIndex.User, ServiceName.Encode("prepo:u"), PrepoMaxSessionsCount);
_serverManager.RegisterServer((int)PrepoPortIndex.System, ServiceName.Encode("prepo:s"), PrepoMaxSessionsCount);
_serverManager.RegisterServer((int)PrepoPortIndex.Debug, ServiceName.Encode("prepo:d"), PrepoMaxSessionsCount); // 1.0.0
_serverManager.RegisterServer((int)PrepoPortIndex.Admin, ServiceName.Encode("prepo:a"), MaxSessionsCount); // 1.0.0-5.1.0
_serverManager.RegisterServer((int)PrepoPortIndex.Admin2, ServiceName.Encode("prepo:a2"), MaxSessionsCount); // 6.0.0+
_serverManager.RegisterServer((int)PrepoPortIndex.Manager, ServiceName.Encode("prepo:m"), MaxSessionsCount);
_serverManager.RegisterServer((int)PrepoPortIndex.User, ServiceName.Encode("prepo:u"), MaxSessionsCount);
_serverManager.RegisterServer((int)PrepoPortIndex.System, ServiceName.Encode("prepo:s"), MaxSessionsCount);
_serverManager.RegisterServer((int)PrepoPortIndex.Debug, ServiceName.Encode("prepo:d"), MaxSessionsCount); // 1.0.0
#pragma warning restore IDE0055
}

View File

@ -0,0 +1,20 @@
using Ryujinx.Horizon.Common;
using Ryujinx.Horizon.Sdk.Sf;
namespace Ryujinx.Horizon.Sdk.Lbl
{
interface ILblController : IServiceObject
{
Result SetBrightnessReflectionDelayLevel(float unknown0, float unknown1);
Result GetBrightnessReflectionDelayLevel(out float unknown1, float unknown0);
Result SetCurrentBrightnessMapping(float unknown0, float unknown1, float unknown2);
Result GetCurrentBrightnessMapping(out float unknown0, out float unknown1, out float unknown2);
Result SetCurrentAmbientLightSensorMapping(float unknown0, float unknown1, float unknown2);
Result GetCurrentAmbientLightSensorMapping(out float unknown0, out float unknown1, out float unknown2);
Result SetCurrentBrightnessSettingForVrMode(float currentBrightnessSettingForVrMode);
Result GetCurrentBrightnessSettingForVrMode(out float currentBrightnessSettingForVrMode);
Result EnableVrMode();
Result DisableVrMode();
Result IsVrModeEnabled(out bool vrModeEnabled);
}
}

View File

@ -0,0 +1,43 @@
using Ryujinx.Horizon.Common;
using Ryujinx.Horizon.Sdk.Sm;
using System;
namespace Ryujinx.Horizon.Sdk.Lbl
{
public class LblApi : IDisposable
{
private const string LblName = "lbl";
private int _sessionHandle;
public LblApi()
{
using var smApi = new SmApi();
smApi.Initialize();
smApi.GetServiceHandle(out _sessionHandle, ServiceName.Encode(LblName)).AbortOnFailure();
}
public Result EnableVrMode()
{
return ServiceUtil.SendRequest(out _, _sessionHandle, 26, sendPid: false, ReadOnlySpan<byte>.Empty);
}
public Result DisableVrMode()
{
return ServiceUtil.SendRequest(out _, _sessionHandle, 27, sendPid: false, ReadOnlySpan<byte>.Empty);
}
public void Dispose()
{
if (_sessionHandle != 0)
{
HorizonStatic.Syscall.CloseHandle(_sessionHandle);
_sessionHandle = 0;
}
GC.SuppressFinalize(this);
}
}
}

View File

@ -4,7 +4,7 @@ using System.Runtime.InteropServices;
namespace Ryujinx.Horizon.Sdk.Sm
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
readonly struct ServiceName
public readonly struct ServiceName
{
public static ServiceName Invalid { get; } = new(0);

View File

@ -5,7 +5,7 @@ using System;
namespace Ryujinx.Horizon.Sdk.Sm
{
class SmApi
public class SmApi : IDisposable
{
private const string SmName = "sm:";
@ -109,5 +109,17 @@ namespace Ryujinx.Horizon.Sdk.Sm
return ServiceUtil.SendRequest(out _, _portHandle, 4, sendPid: true, data);
}
public void Dispose()
{
if (_portHandle != 0)
{
HorizonStatic.Syscall.CloseHandle(_portHandle);
_portHandle = 0;
}
GC.SuppressFinalize(this);
}
}
}

View File

@ -0,0 +1,8 @@
using Ryujinx.Horizon.Sdk.Sf;
namespace Ryujinx.Horizon.Sdk.Wlan
{
interface IDetectManager : IServiceObject
{
}
}

View File

@ -0,0 +1,8 @@
using Ryujinx.Horizon.Sdk.Sf;
namespace Ryujinx.Horizon.Sdk.Wlan
{
interface IGeneralServiceCreator : IServiceObject
{
}
}

View File

@ -0,0 +1,8 @@
using Ryujinx.Horizon.Sdk.Sf;
namespace Ryujinx.Horizon.Sdk.Wlan
{
interface IInfraManager : IServiceObject
{
}
}

View File

@ -0,0 +1,8 @@
using Ryujinx.Horizon.Sdk.Sf;
namespace Ryujinx.Horizon.Sdk.Wlan
{
interface ILocalGetActionFrame : IServiceObject
{
}
}

View File

@ -0,0 +1,8 @@
using Ryujinx.Horizon.Sdk.Sf;
namespace Ryujinx.Horizon.Sdk.Wlan
{
interface ILocalGetFrame : IServiceObject
{
}
}

View File

@ -0,0 +1,8 @@
using Ryujinx.Horizon.Sdk.Sf;
namespace Ryujinx.Horizon.Sdk.Wlan
{
interface ILocalManager : IServiceObject
{
}
}

View File

@ -0,0 +1,8 @@
using Ryujinx.Horizon.Sdk.Sf;
namespace Ryujinx.Horizon.Sdk.Wlan
{
interface IPrivateServiceCreator : IServiceObject
{
}
}

View File

@ -0,0 +1,8 @@
using Ryujinx.Horizon.Sdk.Sf;
namespace Ryujinx.Horizon.Sdk.Wlan
{
interface ISfDriverServiceCreator : IServiceObject
{
}
}

View File

@ -0,0 +1,8 @@
using Ryujinx.Horizon.Sdk.Sf;
namespace Ryujinx.Horizon.Sdk.Wlan
{
interface ISocketGetFrame : IServiceObject
{
}
}

View File

@ -0,0 +1,8 @@
using Ryujinx.Horizon.Sdk.Sf;
namespace Ryujinx.Horizon.Sdk.Wlan
{
interface ISocketManager : IServiceObject
{
}
}

View File

@ -1,7 +1,9 @@
using Ryujinx.Horizon.Bcat;
using Ryujinx.Horizon.Lbl;
using Ryujinx.Horizon.LogManager;
using Ryujinx.Horizon.MmNv;
using Ryujinx.Horizon.Prepo;
using Ryujinx.Horizon.Wlan;
using System.Collections.Generic;
using System.Threading;
@ -23,10 +25,12 @@ namespace Ryujinx.Horizon
entries.Add(new ServiceEntry(T.Main, this, options));
}
RegisterService<LmMain>();
RegisterService<PrepoMain>();
RegisterService<BcatMain>();
RegisterService<LblMain>();
RegisterService<LmMain>();
RegisterService<MmNvMain>();
RegisterService<PrepoMain>();
RegisterService<WlanMain>();
_totalServices = entries.Count;

View File

@ -0,0 +1,8 @@
using Ryujinx.Horizon.Sdk.Wlan;
namespace Ryujinx.Horizon.Wlan.Ipc
{
partial class DetectManager : IDetectManager
{
}
}

View File

@ -0,0 +1,8 @@
using Ryujinx.Horizon.Sdk.Wlan;
namespace Ryujinx.Horizon.Wlan.Ipc
{
partial class GeneralServiceCreator : IGeneralServiceCreator
{
}
}

View File

@ -0,0 +1,8 @@
using Ryujinx.Horizon.Sdk.Wlan;
namespace Ryujinx.Horizon.Wlan.Ipc
{
partial class InfraManager : IInfraManager
{
}
}

View File

@ -0,0 +1,8 @@
using Ryujinx.Horizon.Sdk.Wlan;
namespace Ryujinx.Horizon.Wlan.Ipc
{
partial class LocalGetActionFrame : ILocalGetActionFrame
{
}
}

View File

@ -0,0 +1,8 @@
using Ryujinx.Horizon.Sdk.Wlan;
namespace Ryujinx.Horizon.Wlan.Ipc
{
partial class LocalGetFrame : ILocalGetFrame
{
}
}

View File

@ -0,0 +1,8 @@
using Ryujinx.Horizon.Sdk.Wlan;
namespace Ryujinx.Horizon.Wlan.Ipc
{
partial class LocalManager : ILocalManager
{
}
}

View File

@ -0,0 +1,8 @@
using Ryujinx.Horizon.Sdk.Wlan;
namespace Ryujinx.Horizon.Wlan.Ipc
{
partial class PrivateServiceCreator : IPrivateServiceCreator
{
}
}

View File

@ -0,0 +1,8 @@
using Ryujinx.Horizon.Sdk.Wlan;
namespace Ryujinx.Horizon.Wlan.Ipc
{
partial class SfDriverServiceCreator : ISfDriverServiceCreator
{
}
}

View File

@ -0,0 +1,8 @@
using Ryujinx.Horizon.Sdk.Wlan;
namespace Ryujinx.Horizon.Wlan.Ipc
{
partial class SocketGetFrame : ISocketGetFrame
{
}
}

View File

@ -0,0 +1,8 @@
using Ryujinx.Horizon.Sdk.Wlan;
namespace Ryujinx.Horizon.Wlan.Ipc
{
partial class SocketManager : ISocketManager
{
}
}

View File

@ -0,0 +1,59 @@
using Ryujinx.Horizon.Sdk.Sf.Hipc;
using Ryujinx.Horizon.Sdk.Sm;
using Ryujinx.Horizon.Wlan.Ipc;
namespace Ryujinx.Horizon.Wlan
{
class WlanIpcServer
{
private const int WlanOtherMaxSessionsCount = 10;
private const int WlanDtcMaxSessionsCount = 4;
private const int WlanMaxSessionsCount = 30;
private const int WlanNdMaxSessionsCount = 5;
private const int WlanPMaxSessionsCount = 30;
private const int TotalMaxSessionsCount = WlanDtcMaxSessionsCount + WlanMaxSessionsCount + WlanNdMaxSessionsCount + WlanPMaxSessionsCount + WlanOtherMaxSessionsCount * 6;
private const int PointerBufferSize = 0x1000;
private const int MaxDomains = 16;
private const int MaxDomainObjects = 10;
private const int MaxPortsCount = 10;
private static readonly ManagerOptions _options = new(PointerBufferSize, MaxDomains, MaxDomainObjects, false);
private SmApi _sm;
private ServerManager _serverManager;
public void Initialize()
{
HeapAllocator allocator = new();
_sm = new SmApi();
_sm.Initialize().AbortOnFailure();
_serverManager = new ServerManager(allocator, _sm, MaxPortsCount, _options, TotalMaxSessionsCount);
#pragma warning disable IDE0055 // Disable formatting
_serverManager.RegisterObjectForServer(new GeneralServiceCreator(), ServiceName.Encode("wlan"), WlanMaxSessionsCount); // 15.0.0+
_serverManager.RegisterObjectForServer(new DetectManager(), ServiceName.Encode("wlan:dtc"), WlanDtcMaxSessionsCount); // 6.0.0-14.1.2
_serverManager.RegisterObjectForServer(new InfraManager(), ServiceName.Encode("wlan:inf"), WlanOtherMaxSessionsCount); // 1.0.0-14.1.2
_serverManager.RegisterObjectForServer(new LocalManager(), ServiceName.Encode("wlan:lcl"), WlanOtherMaxSessionsCount); // 1.0.0-14.1.2
_serverManager.RegisterObjectForServer(new LocalGetFrame(), ServiceName.Encode("wlan:lg"), WlanOtherMaxSessionsCount); // 1.0.0-14.1.2
_serverManager.RegisterObjectForServer(new LocalGetActionFrame(), ServiceName.Encode("wlan:lga"), WlanOtherMaxSessionsCount); // 1.0.0-14.1.2
_serverManager.RegisterObjectForServer(new SfDriverServiceCreator(), ServiceName.Encode("wlan:nd"), WlanNdMaxSessionsCount); // 15.0.0+
_serverManager.RegisterObjectForServer(new PrivateServiceCreator(), ServiceName.Encode("wlan:p"), WlanPMaxSessionsCount); // 15.0.0+
_serverManager.RegisterObjectForServer(new SocketGetFrame(), ServiceName.Encode("wlan:sg"), WlanOtherMaxSessionsCount); // 1.0.0-14.1.2
_serverManager.RegisterObjectForServer(new SocketManager(), ServiceName.Encode("wlan:soc"), WlanOtherMaxSessionsCount); // 1.0.0-14.1.2
#pragma warning restore IDE0055
}
public void ServiceRequests()
{
_serverManager.ServiceRequests();
}
public void Shutdown()
{
_serverManager.Dispose();
}
}
}

View File

@ -0,0 +1,17 @@
namespace Ryujinx.Horizon.Wlan
{
class WlanMain : IService
{
public static void Main(ServiceTable serviceTable)
{
WlanIpcServer ipcServer = new();
ipcServer.Initialize();
serviceTable.SignalServiceReady();
ipcServer.ServiceRequests();
ipcServer.Shutdown();
}
}
}