Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
7ccff037e8 | |||
a745913329 | |||
e6700b314f | |||
e2cfe6fe44 | |||
210f475484 | |||
ddb6493896 | |||
f631933e60 |
15
.github/workflows/build.yml
vendored
15
.github/workflows/build.yml
vendored
@ -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'
|
10
.github/workflows/release.yml
vendored
10
.github/workflows/release.yml
vendored
@ -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
|
||||
|
111
distribution/macos/create_macos_build_headless.sh
Executable file
111
distribution/macos/create_macos_build_headless.sh
Executable 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"
|
@ -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)
|
||||
|
@ -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>
|
||||
|
@ -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) });
|
||||
|
@ -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";
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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];
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ using System;
|
||||
|
||||
namespace Ryujinx.Horizon
|
||||
{
|
||||
static class HorizonStatic
|
||||
public static class HorizonStatic
|
||||
{
|
||||
[ThreadStatic]
|
||||
private static HorizonOptions _options;
|
||||
|
130
src/Ryujinx.Horizon/Lbl/Ipc/LblController.cs
Normal file
130
src/Ryujinx.Horizon/Lbl/Ipc/LblController.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
43
src/Ryujinx.Horizon/Lbl/LblIpcServer.cs
Normal file
43
src/Ryujinx.Horizon/Lbl/LblIpcServer.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
17
src/Ryujinx.Horizon/Lbl/LblMain.cs
Normal file
17
src/Ryujinx.Horizon/Lbl/LblMain.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
20
src/Ryujinx.Horizon/Sdk/Lbl/ILblController.cs
Normal file
20
src/Ryujinx.Horizon/Sdk/Lbl/ILblController.cs
Normal 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);
|
||||
}
|
||||
}
|
43
src/Ryujinx.Horizon/Sdk/Lbl/LblApi.cs
Normal file
43
src/Ryujinx.Horizon/Sdk/Lbl/LblApi.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Ryujinx.Horizon.Bcat;
|
||||
using Ryujinx.Horizon.Lbl;
|
||||
using Ryujinx.Horizon.LogManager;
|
||||
using Ryujinx.Horizon.MmNv;
|
||||
using Ryujinx.Horizon.Prepo;
|
||||
@ -23,10 +24,11 @@ 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>();
|
||||
|
||||
_totalServices = entries.Count;
|
||||
|
||||
|
Reference in New Issue
Block a user