Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
51a27032f0 | |||
a6a67a2b7a | |||
c6d05301aa | |||
647de4cd31 | |||
f82309fa2d | |||
7d8e198c33 | |||
3d98e1361b | |||
141cf61ff7 | |||
3fe3598d41 | |||
59cdf310bd |
3
.github/workflows/build.yml
vendored
3
.github/workflows/build.yml
vendored
@ -51,12 +51,13 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
dotnet-version: 7.0.x
|
||||
- name: Ensure NuGet Source
|
||||
uses: fabriciomurta/ensure-nuget-source@v1
|
||||
- name: Get git short hash
|
||||
id: git_short_hash
|
||||
run: echo "result=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
- name: Clear
|
||||
run: dotnet clean && dotnet nuget locals all --clear
|
||||
- name: Build
|
||||
|
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@ -28,7 +28,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
dotnet-version: 7.0.x
|
||||
- name: Ensure NuGet Source
|
||||
uses: fabriciomurta/ensure-nuget-source@v1
|
||||
- name: Clear
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -62,7 +62,7 @@ The latest automatic build for Windows, macOS, and Linux can be found on the [Of
|
||||
If you wish to build the emulator yourself, follow these steps:
|
||||
|
||||
### Step 1
|
||||
Install the X64 version of [.NET 6.0 (or higher) SDK](https://dotnet.microsoft.com/download/dotnet/6.0).
|
||||
Install the X64 version of [.NET 7.0 (or higher) SDK](https://dotnet.microsoft.com/download/dotnet/7.0).
|
||||
|
||||
### Step 2
|
||||
Either use `git clone https://github.com/Ryujinx/Ryujinx` on the command line to clone the repository or use Code --> Download zip button to get the files.
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<RuntimeIdentifiers>win10-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
</PropertyGroup>
|
||||
|
@ -150,7 +150,7 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter
|
||||
/// </summary>
|
||||
/// <param name="inputHeader">The splitter header.</param>
|
||||
/// <param name="input">The raw data after the splitter header.</param>
|
||||
private void UpdateState(ref SplitterInParameterHeader inputHeader, ref ReadOnlySpan<byte> input)
|
||||
private void UpdateState(scoped ref SplitterInParameterHeader inputHeader, ref ReadOnlySpan<byte> input)
|
||||
{
|
||||
for (int i = 0; i < inputHeader.SplitterCount; i++)
|
||||
{
|
||||
@ -177,7 +177,7 @@ namespace Ryujinx.Audio.Renderer.Server.Splitter
|
||||
/// </summary>
|
||||
/// <param name="inputHeader">The splitter header.</param>
|
||||
/// <param name="input">The raw data after the splitter header.</param>
|
||||
private void UpdateData(ref SplitterInParameterHeader inputHeader, ref ReadOnlySpan<byte> input)
|
||||
private void UpdateData(scoped ref SplitterInParameterHeader inputHeader, ref ReadOnlySpan<byte> input)
|
||||
{
|
||||
for (int i = 0; i < inputHeader.SplitterDestinationCount; i++)
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<RuntimeIdentifiers>win10-x64;osx-x64;linux-x64</RuntimeIdentifiers>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
@ -8,11 +8,13 @@
|
||||
<DefineConstants Condition=" '$(ExtraDefineConstants)' != '' ">$(DefineConstants);$(ExtraDefineConstants)</DefineConstants>
|
||||
<RootNamespace>Ryujinx.Ava</RootNamespace>
|
||||
<ApplicationIcon>Ryujinx.ico</ApplicationIcon>
|
||||
<TieredPGO>true</TieredPGO>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(RuntimeIdentifier)' != ''">
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
<PublishTrimmed>true</PublishTrimmed>
|
||||
<TrimMode>partial</TrimMode>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -53,5 +53,11 @@ namespace Ryujinx.Common
|
||||
|
||||
writer.Write(data);
|
||||
}
|
||||
|
||||
public static void Write(this BinaryWriter writer, UInt128 value)
|
||||
{
|
||||
writer.Write((ulong)value);
|
||||
writer.Write((ulong)(value >> 64));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -7,19 +7,19 @@ namespace Ryujinx.Common.Utilities
|
||||
public static class SpanHelpers
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Span<T> CreateSpan<T>(ref T reference, int length)
|
||||
public static Span<T> CreateSpan<T>(scoped ref T reference, int length)
|
||||
{
|
||||
return MemoryMarshal.CreateSpan(ref reference, length);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Span<T> AsSpan<T>(ref T reference) where T : unmanaged
|
||||
public static Span<T> AsSpan<T>(scoped ref T reference) where T : unmanaged
|
||||
{
|
||||
return CreateSpan(ref reference, 1);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Span<TSpan> AsSpan<TStruct, TSpan>(ref TStruct reference)
|
||||
public static Span<TSpan> AsSpan<TStruct, TSpan>(scoped ref TStruct reference)
|
||||
where TStruct : unmanaged where TSpan : unmanaged
|
||||
{
|
||||
return CreateSpan(ref Unsafe.As<TStruct, TSpan>(ref reference),
|
||||
@ -27,25 +27,25 @@ namespace Ryujinx.Common.Utilities
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Span<byte> AsByteSpan<T>(ref T reference) where T : unmanaged
|
||||
public static Span<byte> AsByteSpan<T>(scoped ref T reference) where T : unmanaged
|
||||
{
|
||||
return CreateSpan(ref Unsafe.As<T, byte>(ref reference), Unsafe.SizeOf<T>());
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ReadOnlySpan<T> CreateReadOnlySpan<T>(ref T reference, int length)
|
||||
public static ReadOnlySpan<T> CreateReadOnlySpan<T>(scoped ref T reference, int length)
|
||||
{
|
||||
return MemoryMarshal.CreateReadOnlySpan(ref reference, length);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ReadOnlySpan<T> AsReadOnlySpan<T>(ref T reference) where T : unmanaged
|
||||
public static ReadOnlySpan<T> AsReadOnlySpan<T>(scoped ref T reference) where T : unmanaged
|
||||
{
|
||||
return CreateReadOnlySpan(ref reference, 1);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ReadOnlySpan<TSpan> AsReadOnlySpan<TStruct, TSpan>(ref TStruct reference)
|
||||
public static ReadOnlySpan<TSpan> AsReadOnlySpan<TStruct, TSpan>(scoped ref TStruct reference)
|
||||
where TStruct : unmanaged where TSpan : unmanaged
|
||||
{
|
||||
return CreateReadOnlySpan(ref Unsafe.As<TStruct, TSpan>(ref reference),
|
||||
@ -53,7 +53,7 @@ namespace Ryujinx.Common.Utilities
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ReadOnlySpan<byte> AsReadOnlyByteSpan<T>(ref T reference) where T : unmanaged
|
||||
public static ReadOnlySpan<byte> AsReadOnlyByteSpan<T>(scoped ref T reference) where T : unmanaged
|
||||
{
|
||||
return CreateReadOnlySpan(ref Unsafe.As<T, byte>(ref reference), Unsafe.SizeOf<T>());
|
||||
}
|
||||
|
17
Ryujinx.Common/Utilities/UInt128Utils.cs
Normal file
17
Ryujinx.Common/Utilities/UInt128Utils.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Common.Utilities
|
||||
{
|
||||
public static class UInt128Utils
|
||||
{
|
||||
public static UInt128 FromHex(string hex)
|
||||
{
|
||||
return new UInt128((ulong)Convert.ToInt64(hex.Substring(0, 16), 16), (ulong)Convert.ToInt64(hex.Substring(16), 16));
|
||||
}
|
||||
|
||||
public static UInt128 CreateRandom()
|
||||
{
|
||||
return new UInt128((ulong)Random.Shared.NextInt64(), (ulong)Random.Shared.NextInt64());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
|
@ -94,6 +94,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
|
||||
{
|
||||
var memoryManager = _channel.MemoryManager;
|
||||
|
||||
// Since we're going to change the state, make sure any pending instanced draws are done.
|
||||
_3dEngine.PerformDeferredDraws();
|
||||
|
||||
// Make sure all pending uniform buffer data is written to memory.
|
||||
_3dEngine.FlushUboDirty();
|
||||
|
||||
uint qmdAddress = _state.State.SendPcasA;
|
||||
|
@ -708,11 +708,12 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
else
|
||||
{
|
||||
bool dataMatches = _currentData != null && data.SequenceEqual(_currentData);
|
||||
_currentData = data.ToArray();
|
||||
if (dataMatches)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_currentData = data.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -413,10 +413,10 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void UpdateCachedBuffer(
|
||||
int stageIndex,
|
||||
ref int cachedTextureBufferIndex,
|
||||
ref int cachedSamplerBufferIndex,
|
||||
ref ReadOnlySpan<int> cachedTextureBuffer,
|
||||
ref ReadOnlySpan<int> cachedSamplerBuffer,
|
||||
scoped ref int cachedTextureBufferIndex,
|
||||
scoped ref int cachedSamplerBufferIndex,
|
||||
scoped ref ReadOnlySpan<int> cachedTextureBuffer,
|
||||
scoped ref ReadOnlySpan<int> cachedSamplerBuffer,
|
||||
int textureBufferIndex,
|
||||
int samplerBufferIndex)
|
||||
{
|
||||
|
@ -710,7 +710,12 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
break;
|
||||
case Target.Texture2DMultisample:
|
||||
case Target.Texture2DMultisampleArray:
|
||||
if (rhs.Target == Target.Texture2D || rhs.Target == Target.Texture2DArray)
|
||||
// We don't support copy between multisample and non-multisample depth-stencil textures
|
||||
// because there's no way to emulate that since most GPUs don't support writing a
|
||||
// custom stencil value into the texture, among several other API limitations.
|
||||
|
||||
if ((rhs.Target == Target.Texture2D || rhs.Target == Target.Texture2DArray) &&
|
||||
!rhs.FormatInfo.Format.IsDepthOrStencil())
|
||||
{
|
||||
return TextureViewCompatibility.CopyOnly;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -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 = 3781;
|
||||
private const uint CodeGenVersion = 3833;
|
||||
|
||||
private const string SharedTocFileName = "shared.toc";
|
||||
private const string SharedDataFileName = "shared.data";
|
||||
|
@ -350,7 +350,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.HashTable
|
||||
/// <param name="item">The item on the table, if found, otherwise unmodified</param>
|
||||
/// <param name="data">The data on the table, if found, otherwise unmodified</param>
|
||||
/// <returns>Table lookup result</returns>
|
||||
public SearchResult TryFindItem(ref SmartDataAccessor dataAccessor, int size, ref T item, ref byte[] data)
|
||||
public SearchResult TryFindItem(scoped ref SmartDataAccessor dataAccessor, int size, scoped ref T item, scoped ref byte[] data)
|
||||
{
|
||||
if (_count == 0)
|
||||
{
|
||||
|
@ -91,7 +91,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.HashTable
|
||||
/// <param name="item">The item on the table, if found, otherwise unmodified</param>
|
||||
/// <param name="data">The data on the table, if found, otherwise unmodified</param>
|
||||
/// <returns>Table lookup result</returns>
|
||||
public PartitionHashTable<T>.SearchResult TryFindItem(ref SmartDataAccessor dataAccessor, ref T item, ref byte[] data)
|
||||
public PartitionHashTable<T>.SearchResult TryFindItem(scoped ref SmartDataAccessor dataAccessor, scoped ref T item, scoped ref byte[] data)
|
||||
{
|
||||
return _table.TryFindItem(ref dataAccessor, Size, ref item, ref data);
|
||||
}
|
||||
|
@ -552,11 +552,11 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||
private static void UpdateCachedBuffer(
|
||||
GpuChannel channel,
|
||||
bool isCompute,
|
||||
ref int cachedTextureBufferIndex,
|
||||
ref int cachedSamplerBufferIndex,
|
||||
ref ReadOnlySpan<int> cachedTextureBuffer,
|
||||
ref ReadOnlySpan<int> cachedSamplerBuffer,
|
||||
ref int cachedStageIndex,
|
||||
scoped ref int cachedTextureBufferIndex,
|
||||
scoped ref int cachedSamplerBufferIndex,
|
||||
scoped ref ReadOnlySpan<int> cachedTextureBuffer,
|
||||
scoped ref ReadOnlySpan<int> cachedSamplerBuffer,
|
||||
scoped ref int cachedStageIndex,
|
||||
int textureBufferIndex,
|
||||
int samplerBufferIndex,
|
||||
int stageIndex)
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -7,7 +7,9 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg
|
||||
{
|
||||
unsafe class FFmpegContext : IDisposable
|
||||
{
|
||||
private readonly FFCodec.AVCodec_decode _decodeFrame;
|
||||
private unsafe delegate int AVCodec_decode(AVCodecContext* avctx, void* outdata, int* got_frame_ptr, AVPacket* avpkt);
|
||||
|
||||
private readonly AVCodec_decode _decodeFrame;
|
||||
private static readonly FFmpegApi.av_log_set_callback_callback _logFunc;
|
||||
private readonly AVCodec* _codec;
|
||||
private AVPacket* _packet;
|
||||
@ -53,17 +55,17 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg
|
||||
// libavcodec 59.24 changed AvCodec to move its private API and also move the codec function to an union.
|
||||
if (avCodecMajorVersion > 59 || (avCodecMajorVersion == 59 && avCodecMinorVersion > 24))
|
||||
{
|
||||
_decodeFrame = Marshal.GetDelegateForFunctionPointer<FFCodec.AVCodec_decode>(((FFCodec*)_codec)->CodecCallback);
|
||||
_decodeFrame = Marshal.GetDelegateForFunctionPointer<AVCodec_decode>(((FFCodec<AVCodec>*)_codec)->CodecCallback);
|
||||
}
|
||||
// libavcodec 59.x changed AvCodec private API layout.
|
||||
else if (avCodecMajorVersion == 59)
|
||||
{
|
||||
_decodeFrame = Marshal.GetDelegateForFunctionPointer<FFCodec.AVCodec_decode>(((FFCodecLegacy<AVCodec>*)_codec)->Decode);
|
||||
_decodeFrame = Marshal.GetDelegateForFunctionPointer<AVCodec_decode>(((FFCodecLegacy<AVCodec501>*)_codec)->Decode);
|
||||
}
|
||||
// libavcodec 58.x and lower
|
||||
else
|
||||
{
|
||||
_decodeFrame = Marshal.GetDelegateForFunctionPointer<FFCodec.AVCodec_decode>(((FFCodecLegacy<AVCodecLegacy>*)_codec)->Decode);
|
||||
_decodeFrame = Marshal.GetDelegateForFunctionPointer<AVCodec_decode>(((FFCodecLegacy<AVCodec>*)_codec)->Decode);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||
public unsafe IntPtr PrivClass;
|
||||
public IntPtr Profiles;
|
||||
public unsafe byte* WrapperName;
|
||||
public IntPtr ChLayouts;
|
||||
#pragma warning restore CS0649
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||
{
|
||||
struct AVCodecLegacy
|
||||
struct AVCodec501
|
||||
{
|
||||
#pragma warning disable CS0649
|
||||
public unsafe byte* Name;
|
||||
@ -20,7 +20,6 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||
public unsafe IntPtr PrivClass;
|
||||
public IntPtr Profiles;
|
||||
public unsafe byte* WrapperName;
|
||||
public IntPtr ChLayouts;
|
||||
#pragma warning restore CS0649
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||
public unsafe IntPtr AvClass;
|
||||
public int LogLevelOffset;
|
||||
public int CodecType;
|
||||
public unsafe AVCodecLegacy* Codec;
|
||||
public unsafe AVCodec* Codec;
|
||||
public AVCodecID CodecId;
|
||||
public uint CodecTag;
|
||||
public IntPtr PrivData;
|
||||
|
@ -2,12 +2,10 @@
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||
{
|
||||
struct FFCodec
|
||||
struct FFCodec<T> where T: struct
|
||||
{
|
||||
public unsafe delegate int AVCodec_decode(AVCodecContext* avctx, void* outdata, int* got_frame_ptr, AVPacket* avpkt);
|
||||
|
||||
#pragma warning disable CS0649
|
||||
public AVCodec Base;
|
||||
public T Base;
|
||||
public int CapsInternalOrCbType;
|
||||
public int PrivDataSize;
|
||||
public IntPtr UpdateThreadContext;
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -34,5 +34,11 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||
GL.ActiveTexture(TextureUnit.Texture0 + unit);
|
||||
GL.BindTexture(target, Handle);
|
||||
}
|
||||
|
||||
public static void ClearBinding(int unit)
|
||||
{
|
||||
GL.ActiveTexture(TextureUnit.Texture0 + unit);
|
||||
GL.BindTextureUnit(unit, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||
|
||||
if (!destinationView.Target.IsMultisample() && Target.IsMultisample())
|
||||
{
|
||||
_renderer.TextureCopyMS.CopyMSToNonMS(this, destinationView, srcLayer, dstLayer,1);
|
||||
_renderer.TextureCopyMS.CopyMSToNonMS(this, destinationView, srcLayer, dstLayer, 1);
|
||||
}
|
||||
else if (destinationView.Target.IsMultisample() && !Target.IsMultisample())
|
||||
{
|
||||
|
@ -919,6 +919,7 @@ namespace Ryujinx.Graphics.OpenGL
|
||||
|
||||
if (texture == null)
|
||||
{
|
||||
GL.BindImageTexture(binding, 0, 0, true, 0, TextureAccess.ReadWrite, SizedInternalFormat.Rgba8);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1275,6 +1276,10 @@ namespace Ryujinx.Graphics.OpenGL
|
||||
((TextureBase)texture).Bind(binding);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TextureBase.ClearBinding(binding);
|
||||
}
|
||||
|
||||
Sampler glSampler = (Sampler)sampler;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -48,6 +48,10 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
{ AttributeConsts.TessCoordY, new BuiltInAttribute("gl_TessCoord.y", VariableType.F32) },
|
||||
{ AttributeConsts.InstanceId, new BuiltInAttribute("gl_InstanceID", VariableType.S32) },
|
||||
{ AttributeConsts.VertexId, new BuiltInAttribute("gl_VertexID", VariableType.S32) },
|
||||
{ AttributeConsts.BaseInstance, new BuiltInAttribute("gl_BaseInstance", VariableType.S32) },
|
||||
{ AttributeConsts.BaseVertex, new BuiltInAttribute("gl_BaseVertex", VariableType.S32) },
|
||||
{ AttributeConsts.InstanceIndex, new BuiltInAttribute("gl_InstanceIndex", VariableType.S32) },
|
||||
{ AttributeConsts.VertexIndex, new BuiltInAttribute("gl_VertexIndex", VariableType.S32) },
|
||||
{ AttributeConsts.FrontFacing, new BuiltInAttribute("gl_FrontFacing", VariableType.Bool) },
|
||||
|
||||
// Special.
|
||||
|
@ -262,6 +262,13 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
|
||||
Instruction ioVariable, elemIndex;
|
||||
|
||||
Instruction invocationId = null;
|
||||
|
||||
if (Config.Stage == ShaderStage.TessellationControl && isOutAttr)
|
||||
{
|
||||
invocationId = Load(TypeS32(), Inputs[AttributeConsts.InvocationId]);
|
||||
}
|
||||
|
||||
bool isUserAttr = attr >= AttributeConsts.UserAttributeBase && attr < AttributeConsts.UserAttributeEnd;
|
||||
|
||||
if (isUserAttr &&
|
||||
@ -273,7 +280,17 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
elemIndex = Constant(TypeU32(), attrInfo.GetInnermostIndex());
|
||||
var vecIndex = Constant(TypeU32(), (attr - AttributeConsts.UserAttributeBase) >> 4);
|
||||
|
||||
if (AttributeInfo.IsArrayAttributeSpirv(Config.Stage, isOutAttr))
|
||||
bool isArray = AttributeInfo.IsArrayAttributeSpirv(Config.Stage, isOutAttr);
|
||||
|
||||
if (invocationId != null && isArray)
|
||||
{
|
||||
return AccessChain(TypePointer(storageClass, GetType(elemType)), ioVariable, invocationId, index, vecIndex, elemIndex);
|
||||
}
|
||||
else if (invocationId != null)
|
||||
{
|
||||
return AccessChain(TypePointer(storageClass, GetType(elemType)), ioVariable, invocationId, vecIndex, elemIndex);
|
||||
}
|
||||
else if (isArray)
|
||||
{
|
||||
return AccessChain(TypePointer(storageClass, GetType(elemType)), ioVariable, index, vecIndex, elemIndex);
|
||||
}
|
||||
@ -308,12 +325,29 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
|
||||
if ((type & (AggregateType.Array | AggregateType.Vector)) == 0)
|
||||
{
|
||||
return isIndexed ? AccessChain(TypePointer(storageClass, GetType(elemType)), ioVariable, index) : ioVariable;
|
||||
if (invocationId != null)
|
||||
{
|
||||
return isIndexed
|
||||
? AccessChain(TypePointer(storageClass, GetType(elemType)), ioVariable, invocationId, index)
|
||||
: AccessChain(TypePointer(storageClass, GetType(elemType)), ioVariable, invocationId);
|
||||
}
|
||||
else
|
||||
{
|
||||
return isIndexed ? AccessChain(TypePointer(storageClass, GetType(elemType)), ioVariable, index) : ioVariable;
|
||||
}
|
||||
}
|
||||
|
||||
elemIndex = Constant(TypeU32(), attrInfo.GetInnermostIndex());
|
||||
|
||||
if (isIndexed)
|
||||
if (invocationId != null && isIndexed)
|
||||
{
|
||||
return AccessChain(TypePointer(storageClass, GetType(elemType)), ioVariable, invocationId, index, elemIndex);
|
||||
}
|
||||
else if (invocationId != null)
|
||||
{
|
||||
return AccessChain(TypePointer(storageClass, GetType(elemType)), ioVariable, invocationId, elemIndex);
|
||||
}
|
||||
else if (isIndexed)
|
||||
{
|
||||
return AccessChain(TypePointer(storageClass, GetType(elemType)), ioVariable, index, elemIndex);
|
||||
}
|
||||
@ -327,12 +361,29 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
{
|
||||
var storageClass = isOutAttr ? StorageClass.Output : StorageClass.Input;
|
||||
|
||||
Instruction invocationId = null;
|
||||
|
||||
if (Config.Stage == ShaderStage.TessellationControl && isOutAttr)
|
||||
{
|
||||
invocationId = Load(TypeS32(), Inputs[AttributeConsts.InvocationId]);
|
||||
}
|
||||
|
||||
elemType = AggregateType.FP32;
|
||||
var ioVariable = isOutAttr ? OutputsArray : InputsArray;
|
||||
var vecIndex = ShiftRightLogical(TypeS32(), attrIndex, Constant(TypeS32(), 2));
|
||||
var elemIndex = BitwiseAnd(TypeS32(), attrIndex, Constant(TypeS32(), 3));
|
||||
|
||||
if (AttributeInfo.IsArrayAttributeSpirv(Config.Stage, isOutAttr))
|
||||
bool isArray = AttributeInfo.IsArrayAttributeSpirv(Config.Stage, isOutAttr);
|
||||
|
||||
if (invocationId != null && isArray)
|
||||
{
|
||||
return AccessChain(TypePointer(storageClass, GetType(elemType)), ioVariable, invocationId, index, vecIndex, elemIndex);
|
||||
}
|
||||
else if (invocationId != null)
|
||||
{
|
||||
return AccessChain(TypePointer(storageClass, GetType(elemType)), ioVariable, invocationId, vecIndex, elemIndex);
|
||||
}
|
||||
else if (isArray)
|
||||
{
|
||||
return AccessChain(TypePointer(storageClass, GetType(elemType)), ioVariable, index, vecIndex, elemIndex);
|
||||
}
|
||||
|
@ -473,6 +473,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
var attrType = context.TypeVector(context.TypeFP32(), (LiteralInteger)4);
|
||||
attrType = context.TypeArray(attrType, context.Constant(context.TypeU32(), (LiteralInteger)MaxAttributes));
|
||||
|
||||
if (context.Config.Stage == ShaderStage.TessellationControl)
|
||||
{
|
||||
attrType = context.TypeArray(attrType, context.Constant(context.TypeU32(), context.Config.ThreadsPerInputPrimitive));
|
||||
}
|
||||
|
||||
var spvType = context.TypePointer(StorageClass.Output, attrType);
|
||||
var spvVar = context.Variable(spvType, StorageClass.Output);
|
||||
|
||||
@ -543,6 +548,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
}
|
||||
}
|
||||
|
||||
if (context.Config.Stage == ShaderStage.TessellationControl && isOutAttr && !perPatch)
|
||||
{
|
||||
attrType = context.TypeArray(attrType, context.Constant(context.TypeU32(), context.Config.ThreadsPerInputPrimitive));
|
||||
}
|
||||
|
||||
var spvType = context.TypePointer(storageClass, attrType);
|
||||
var spvVar = context.Variable(spvType, storageClass);
|
||||
|
||||
@ -634,6 +644,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
attrType = context.TypeArray(attrType, context.Constant(context.TypeU32(), (LiteralInteger)arraySize));
|
||||
}
|
||||
|
||||
if (context.Config.Stage == ShaderStage.TessellationControl && isOutAttr)
|
||||
{
|
||||
attrType = context.TypeArray(attrType, context.Constant(context.TypeU32(), context.Config.ThreadsPerInputPrimitive));
|
||||
}
|
||||
|
||||
var spvType = context.TypePointer(storageClass, attrType);
|
||||
var spvVar = context.Variable(spvType, storageClass);
|
||||
|
||||
@ -689,8 +704,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
AttributeConsts.ClipDistance0 => BuiltIn.ClipDistance,
|
||||
AttributeConsts.PointCoordX => BuiltIn.PointCoord,
|
||||
AttributeConsts.TessCoordX => BuiltIn.TessCoord,
|
||||
AttributeConsts.InstanceId => BuiltIn.InstanceId, // FIXME: Invalid
|
||||
AttributeConsts.VertexId => BuiltIn.VertexId, // FIXME: Invalid
|
||||
AttributeConsts.InstanceId => BuiltIn.InstanceId,
|
||||
AttributeConsts.VertexId => BuiltIn.VertexId,
|
||||
AttributeConsts.BaseInstance => BuiltIn.BaseInstance,
|
||||
AttributeConsts.BaseVertex => BuiltIn.BaseVertex,
|
||||
AttributeConsts.InstanceIndex => BuiltIn.InstanceIndex,
|
||||
AttributeConsts.VertexIndex => BuiltIn.VertexIndex,
|
||||
AttributeConsts.FrontFacing => BuiltIn.FrontFacing,
|
||||
AttributeConsts.FragmentOutputDepth => BuiltIn.FragDepth,
|
||||
AttributeConsts.ThreadKill => BuiltIn.HelperInvocation,
|
||||
|
@ -51,7 +51,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
offset |= AttributeConsts.LoadOutputMask;
|
||||
}
|
||||
|
||||
Operand src = op.P ? AttributePerPatch(offset) : Attribute(offset);
|
||||
Operand src = op.P ? AttributePerPatch(offset) : CreateInputAttribute(context, offset);
|
||||
|
||||
context.Copy(Register(rd), src);
|
||||
}
|
||||
@ -312,5 +312,22 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
|
||||
return attr;
|
||||
}
|
||||
|
||||
private static Operand CreateInputAttribute(EmitterContext context, int attr)
|
||||
{
|
||||
if (context.Config.Options.TargetApi == TargetApi.Vulkan)
|
||||
{
|
||||
if (attr == AttributeConsts.InstanceId)
|
||||
{
|
||||
return context.ISubtract(Attribute(AttributeConsts.InstanceIndex), Attribute(AttributeConsts.BaseInstance));
|
||||
}
|
||||
else if (attr == AttributeConsts.VertexId)
|
||||
{
|
||||
return Attribute(AttributeConsts.VertexIndex);
|
||||
}
|
||||
}
|
||||
|
||||
return Attribute(attr);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -37,7 +37,12 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||
|
||||
Config = config;
|
||||
|
||||
if (config.GpPassthrough)
|
||||
if (config.Stage == ShaderStage.TessellationControl)
|
||||
{
|
||||
// Required to index outputs.
|
||||
Info.Inputs.Add(AttributeConsts.InvocationId);
|
||||
}
|
||||
else if (config.GpPassthrough)
|
||||
{
|
||||
int passthroughAttributes = config.PassthroughAttributes;
|
||||
while (passthroughAttributes != 0)
|
||||
|
@ -95,5 +95,10 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
public const int LtMask = 0x2000040;
|
||||
|
||||
public const int ThreadKill = 0x2000044;
|
||||
|
||||
public const int BaseInstance = 0x2000050;
|
||||
public const int BaseVertex = 0x2000054;
|
||||
public const int InstanceIndex = 0x2000058;
|
||||
public const int VertexIndex = 0x200005c;
|
||||
}
|
||||
}
|
@ -27,6 +27,10 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
{ AttributeConsts.TessCoordY, new AttributeInfo(AttributeConsts.TessCoordX, 1, 3, AggregateType.Vector | AggregateType.FP32) },
|
||||
{ AttributeConsts.InstanceId, new AttributeInfo(AttributeConsts.InstanceId, 0, 1, AggregateType.S32) },
|
||||
{ AttributeConsts.VertexId, new AttributeInfo(AttributeConsts.VertexId, 0, 1, AggregateType.S32) },
|
||||
{ AttributeConsts.BaseInstance, new AttributeInfo(AttributeConsts.BaseInstance, 0, 1, AggregateType.S32) },
|
||||
{ AttributeConsts.BaseVertex, new AttributeInfo(AttributeConsts.BaseVertex, 0, 1, AggregateType.S32) },
|
||||
{ AttributeConsts.InstanceIndex, new AttributeInfo(AttributeConsts.InstanceIndex, 0, 1, AggregateType.S32) },
|
||||
{ AttributeConsts.VertexIndex, new AttributeInfo(AttributeConsts.VertexIndex, 0, 1, AggregateType.S32) },
|
||||
{ AttributeConsts.FrontFacing, new AttributeInfo(AttributeConsts.FrontFacing, 0, 1, AggregateType.Bool) },
|
||||
|
||||
// Special.
|
||||
|
@ -254,7 +254,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
|
||||
UsedInputAttributes |= mask;
|
||||
_thisUsedInputAttributes |= mask;
|
||||
ThisInputAttributesComponents |= UInt128.Pow2(index * 4 + component);
|
||||
ThisInputAttributesComponents |= UInt128.One << (index * 4 + component);
|
||||
}
|
||||
|
||||
public void SetInputUserAttributePerPatch(int index)
|
||||
|
@ -190,10 +190,10 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
UInt128 usedAttributes = context.Config.NextInputAttributesComponents;
|
||||
while (usedAttributes != UInt128.Zero)
|
||||
{
|
||||
int index = usedAttributes.TrailingZeroCount();
|
||||
int index = (int)UInt128.TrailingZeroCount(usedAttributes);
|
||||
int vecIndex = index / 4;
|
||||
|
||||
usedAttributes &= ~UInt128.Pow2(index);
|
||||
usedAttributes &= ~(UInt128.One << index);
|
||||
|
||||
// We don't need to initialize passthrough attributes.
|
||||
if ((context.Config.PassthroughAttributes & (1 << vecIndex)) != 0)
|
||||
|
@ -1,112 +0,0 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader.Translation
|
||||
{
|
||||
struct UInt128 : IEquatable<UInt128>
|
||||
{
|
||||
public static UInt128 Zero => new UInt128() { _v0 = 0, _v1 = 0 };
|
||||
|
||||
private ulong _v0;
|
||||
private ulong _v1;
|
||||
|
||||
public UInt128(ulong low, ulong high)
|
||||
{
|
||||
_v0 = low;
|
||||
_v1 = high;
|
||||
}
|
||||
|
||||
public int TrailingZeroCount()
|
||||
{
|
||||
int count = BitOperations.TrailingZeroCount(_v0);
|
||||
if (count == 64)
|
||||
{
|
||||
count += BitOperations.TrailingZeroCount(_v1);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public static UInt128 Pow2(int x)
|
||||
{
|
||||
if (x >= 64)
|
||||
{
|
||||
return new UInt128(0, 1UL << (x - 64));
|
||||
}
|
||||
|
||||
return new UInt128(1UL << x, 0);
|
||||
}
|
||||
|
||||
public static UInt128 operator ~(UInt128 x)
|
||||
{
|
||||
return new UInt128(~x._v0, ~x._v1);
|
||||
}
|
||||
|
||||
public static UInt128 operator &(UInt128 x, UInt128 y)
|
||||
{
|
||||
return new UInt128(x._v0 & y._v0, x._v1 & y._v1);
|
||||
}
|
||||
|
||||
public static UInt128 operator |(UInt128 x, UInt128 y)
|
||||
{
|
||||
return new UInt128(x._v0 | y._v0, x._v1 | y._v1);
|
||||
}
|
||||
|
||||
public static UInt128 operator <<(UInt128 x, int shift)
|
||||
{
|
||||
if (shift == 0)
|
||||
{
|
||||
return new UInt128(x._v0, x._v1);
|
||||
}
|
||||
else if (shift >= 64)
|
||||
{
|
||||
return new UInt128(0, x._v0 << (shift - 64));
|
||||
}
|
||||
|
||||
ulong shiftOut = x._v0 >> (64 - shift);
|
||||
|
||||
return new UInt128(x._v0 << shift, (x._v1 << shift) | shiftOut);
|
||||
}
|
||||
|
||||
public static UInt128 operator >>(UInt128 x, int shift)
|
||||
{
|
||||
if (shift == 0)
|
||||
{
|
||||
return new UInt128(x._v0, x._v1);
|
||||
}
|
||||
else if (shift >= 64)
|
||||
{
|
||||
return new UInt128(x._v1 >> (shift - 64), 0);
|
||||
}
|
||||
|
||||
ulong shiftOut = x._v1 & ((1UL << shift) - 1);
|
||||
|
||||
return new UInt128((x._v0 >> shift) | (shiftOut << (64 - shift)), x._v1 >> shift);
|
||||
}
|
||||
|
||||
public static bool operator ==(UInt128 x, UInt128 y)
|
||||
{
|
||||
return x.Equals(y);
|
||||
}
|
||||
|
||||
public static bool operator !=(UInt128 x, UInt128 y)
|
||||
{
|
||||
return !x.Equals(y);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is UInt128 other && Equals(other);
|
||||
}
|
||||
|
||||
public bool Equals(UInt128 other)
|
||||
{
|
||||
return _v0 == other._v0 && _v1 == other._v1;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(_v0, _v1);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -229,8 +229,8 @@ namespace Ryujinx.Graphics.Vic.Image
|
||||
|
||||
private static RentedBuffer ReadBuffer(
|
||||
ResourceManager rm,
|
||||
ref SlotConfig config,
|
||||
ref Array8<PlaneOffsets> offsets,
|
||||
scoped ref SlotConfig config,
|
||||
scoped ref Array8<PlaneOffsets> offsets,
|
||||
bool linear,
|
||||
int plane,
|
||||
int width,
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -138,11 +138,6 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
public void SetImage(int binding, ITexture image, GAL.Format imageFormat)
|
||||
{
|
||||
if (image == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (image is TextureBuffer imageBuffer)
|
||||
{
|
||||
_bufferImageRefs[binding] = imageBuffer;
|
||||
@ -152,6 +147,12 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
_imageRefs[binding] = view.GetView(imageFormat).GetIdentityImageView();
|
||||
}
|
||||
else
|
||||
{
|
||||
_imageRefs[binding] = null;
|
||||
_bufferImageRefs[binding] = null;
|
||||
_bufferImageFormats[binding] = default;
|
||||
}
|
||||
|
||||
SignalDirty(DirtyFlags.Image);
|
||||
}
|
||||
@ -215,24 +216,23 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
public void SetTextureAndSampler(CommandBufferScoped cbs, ShaderStage stage, int binding, ITexture texture, ISampler sampler)
|
||||
{
|
||||
if (texture == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (texture is TextureBuffer textureBuffer)
|
||||
{
|
||||
_bufferTextureRefs[binding] = textureBuffer;
|
||||
}
|
||||
else
|
||||
else if (texture is TextureView view)
|
||||
{
|
||||
TextureView view = (TextureView)texture;
|
||||
|
||||
view.Storage.InsertBarrier(cbs, AccessFlags.AccessShaderReadBit, stage.ConvertToPipelineStageFlags());
|
||||
|
||||
_textureRefs[binding] = view.GetImageView();
|
||||
_samplerRefs[binding] = ((SamplerHolder)sampler)?.GetSampler();
|
||||
}
|
||||
else
|
||||
{
|
||||
_textureRefs[binding] = null;
|
||||
_samplerRefs[binding] = null;
|
||||
_bufferTextureRefs[binding] = null;
|
||||
}
|
||||
|
||||
SignalDirty(DirtyFlags.Texture);
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
private readonly IProgram _programColorBlitClearAlpha;
|
||||
private readonly IProgram _programColorClear;
|
||||
private readonly IProgram _programStrideChange;
|
||||
private readonly IProgram _programColorCopyBetweenMsNonMs;
|
||||
|
||||
public HelperShader(VulkanRenderer gd, Device device)
|
||||
{
|
||||
@ -73,6 +74,20 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
new ShaderSource(ShaderBinaries.ChangeBufferStrideShaderSource, strideChangeBindings, ShaderStage.Compute, TargetLanguage.Spirv),
|
||||
});
|
||||
|
||||
var colorCopyMSBindings = new ShaderBindings(
|
||||
new[] { 0 },
|
||||
Array.Empty<int>(),
|
||||
new[] { 0 },
|
||||
new[] { 0 });
|
||||
|
||||
_programColorCopyBetweenMsNonMs = gd.CreateProgramWithMinimalLayout(new[]
|
||||
{
|
||||
new ShaderSource(ShaderBinaries.ColorCopyBetweenMsNonMs, colorCopyMSBindings, ShaderStage.Compute, TargetLanguage.Spirv),
|
||||
}, new[]
|
||||
{
|
||||
new SpecDescription((0, SpecConstType.Int32))
|
||||
});
|
||||
}
|
||||
|
||||
public void Blit(
|
||||
@ -136,11 +151,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
gd.BufferManager.SetData<float>(bufferHandle, 0, region);
|
||||
|
||||
Span<BufferRange> bufferRanges = stackalloc BufferRange[1];
|
||||
|
||||
bufferRanges[0] = new BufferRange(bufferHandle, 0, RegionBufferSize);
|
||||
|
||||
_pipeline.SetUniformBuffers(1, bufferRanges);
|
||||
_pipeline.SetUniformBuffers(1, stackalloc[] { new BufferRange(bufferHandle, 0, RegionBufferSize) });
|
||||
|
||||
Span<GAL.Viewport> viewports = stackalloc GAL.Viewport[1];
|
||||
|
||||
@ -203,11 +214,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
gd.BufferManager.SetData<float>(bufferHandle, 0, clearColor);
|
||||
|
||||
Span<BufferRange> bufferRanges = stackalloc BufferRange[1];
|
||||
|
||||
bufferRanges[0] = new BufferRange(bufferHandle, 0, ClearColorBufferSize);
|
||||
|
||||
_pipeline.SetUniformBuffers(1, bufferRanges);
|
||||
_pipeline.SetUniformBuffers(1, stackalloc[] { new BufferRange(bufferHandle, 0, ClearColorBufferSize) });
|
||||
|
||||
Span<GAL.Viewport> viewports = stackalloc GAL.Viewport[1];
|
||||
|
||||
@ -269,11 +276,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
gd.BufferManager.SetData<float>(bufferHandle, 0, region);
|
||||
|
||||
Span<BufferRange> bufferRanges = stackalloc BufferRange[1];
|
||||
|
||||
bufferRanges[0] = new BufferRange(bufferHandle, 0, RegionBufferSize);
|
||||
|
||||
pipeline.SetUniformBuffers(1, bufferRanges);
|
||||
pipeline.SetUniformBuffers(1, stackalloc[] { new BufferRange(bufferHandle, 0, RegionBufferSize) });
|
||||
|
||||
Span<GAL.Viewport> viewports = stackalloc GAL.Viewport[1];
|
||||
|
||||
@ -351,11 +354,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
_pipeline.SetCommandBuffer(cbs);
|
||||
|
||||
Span<BufferRange> cbRanges = stackalloc BufferRange[1];
|
||||
|
||||
cbRanges[0] = new BufferRange(bufferHandle, 0, ParamsBufferSize);
|
||||
|
||||
_pipeline.SetUniformBuffers(0, cbRanges);
|
||||
_pipeline.SetUniformBuffers(0, stackalloc[] { new BufferRange(bufferHandle, 0, ParamsBufferSize) });
|
||||
|
||||
Span<Auto<DisposableBuffer>> sbRanges = new Auto<DisposableBuffer>[2];
|
||||
|
||||
@ -480,12 +479,207 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
convertedCount * outputIndexSize);
|
||||
}
|
||||
|
||||
public void CopyMSToNonMS(VulkanRenderer gd, CommandBufferScoped cbs, TextureView src, TextureView dst, int srcLayer, int dstLayer, int depth)
|
||||
{
|
||||
CopyMS(gd, cbs, src, dst, srcLayer, dstLayer, depth, src.Info.Samples, dst.Info.Width, dst.Info.Height);
|
||||
}
|
||||
|
||||
public void CopyNonMSToMS(VulkanRenderer gd, CommandBufferScoped cbs, TextureView src, TextureView dst, int srcLayer, int dstLayer, int depth)
|
||||
{
|
||||
CopyMS(gd, cbs, src, dst, srcLayer, dstLayer, depth, dst.Info.Samples, src.Info.Width, src.Info.Height);
|
||||
}
|
||||
|
||||
private void CopyMS(
|
||||
VulkanRenderer gd,
|
||||
CommandBufferScoped cbs,
|
||||
TextureView src,
|
||||
TextureView dst,
|
||||
int srcLayer,
|
||||
int dstLayer,
|
||||
int depth,
|
||||
int samples,
|
||||
int nonMSWidth,
|
||||
int nonMSHeight)
|
||||
{
|
||||
const int ParamsBufferSize = 16;
|
||||
|
||||
Span<int> shaderParams = stackalloc int[ParamsBufferSize / sizeof(int)];
|
||||
|
||||
// X and Y are the expected texture samples.
|
||||
// Z and W are the actual texture samples used.
|
||||
// They may differ if the GPU does not support the samples count requested and we had to use a lower amount.
|
||||
(shaderParams[0], shaderParams[1]) = GetSampleCountXYLog2(samples);
|
||||
(shaderParams[2], shaderParams[3]) = GetSampleCountXYLog2((int)TextureStorage.ConvertToSampleCountFlags((uint)samples));
|
||||
|
||||
var bufferHandle = gd.BufferManager.CreateWithHandle(gd, ParamsBufferSize, false);
|
||||
|
||||
gd.BufferManager.SetData<int>(bufferHandle, 0, shaderParams);
|
||||
|
||||
TextureView.InsertImageBarrier(
|
||||
gd.Api,
|
||||
cbs.CommandBuffer,
|
||||
src.GetImage().Get(cbs).Value,
|
||||
TextureStorage.DefaultAccessMask,
|
||||
AccessFlags.AccessShaderReadBit,
|
||||
PipelineStageFlags.PipelineStageAllCommandsBit,
|
||||
PipelineStageFlags.PipelineStageComputeShaderBit,
|
||||
ImageAspectFlags.ImageAspectColorBit,
|
||||
src.FirstLayer + srcLayer,
|
||||
src.FirstLevel,
|
||||
depth,
|
||||
1);
|
||||
|
||||
_pipeline.SetCommandBuffer(cbs);
|
||||
|
||||
_pipeline.SetProgram(_programColorCopyBetweenMsNonMs);
|
||||
|
||||
var format = GetFormat(src.Info.BytesPerPixel);
|
||||
|
||||
int dispatchX = (nonMSWidth + 31) / 32;
|
||||
int dispatchY = (nonMSHeight + 31) / 32;
|
||||
|
||||
// Specialize shader.
|
||||
bool srcIsMs = src.Info.Target.IsMultisample();
|
||||
int conversionType = srcIsMs ? src.Info.BytesPerPixel : -src.Info.BytesPerPixel;
|
||||
_pipeline.Specialize(conversionType);
|
||||
|
||||
_pipeline.SetUniformBuffers(0, stackalloc[] { new BufferRange(bufferHandle, 0, ParamsBufferSize) });
|
||||
|
||||
if (src.Info.Target == Target.Texture2DMultisampleArray ||
|
||||
dst.Info.Target == Target.Texture2DMultisampleArray)
|
||||
{
|
||||
for (int z = 0; z < depth; z++)
|
||||
{
|
||||
var srcView = Create2DLayerView(src, srcLayer + z, format);
|
||||
var dstView = Create2DLayerView(dst, dstLayer + z);
|
||||
|
||||
_pipeline.SetTextureAndSampler(ShaderStage.Compute, 0, srcView, null);
|
||||
_pipeline.SetImage(0, dstView, format);
|
||||
|
||||
_pipeline.DispatchCompute(dispatchX, dispatchY, 1);
|
||||
|
||||
srcView.Release();
|
||||
dstView.Release();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var srcView = Create2DLayerView(src, srcLayer, format);
|
||||
|
||||
_pipeline.SetTextureAndSampler(ShaderStage.Compute, 0, srcView, null);
|
||||
_pipeline.SetImage(0, dst, format);
|
||||
|
||||
_pipeline.DispatchCompute(dispatchX, dispatchY, 1);
|
||||
|
||||
srcView.Release();
|
||||
}
|
||||
|
||||
gd.BufferManager.Delete(bufferHandle);
|
||||
|
||||
_pipeline.Finish(gd, cbs);
|
||||
|
||||
TextureView.InsertImageBarrier(
|
||||
gd.Api,
|
||||
cbs.CommandBuffer,
|
||||
dst.GetImage().Get(cbs).Value,
|
||||
AccessFlags.AccessShaderWriteBit,
|
||||
TextureStorage.DefaultAccessMask,
|
||||
PipelineStageFlags.PipelineStageComputeShaderBit,
|
||||
PipelineStageFlags.PipelineStageAllCommandsBit,
|
||||
ImageAspectFlags.ImageAspectColorBit,
|
||||
dst.FirstLayer + dstLayer,
|
||||
dst.FirstLevel,
|
||||
depth,
|
||||
1);
|
||||
}
|
||||
|
||||
private static (int, int) GetSampleCountXYLog2(int samples)
|
||||
{
|
||||
int samplesInXLog2 = 0;
|
||||
int samplesInYLog2 = 0;
|
||||
|
||||
switch (samples)
|
||||
{
|
||||
case 2: // 2x1
|
||||
samplesInXLog2 = 1;
|
||||
break;
|
||||
case 4: // 2x2
|
||||
samplesInXLog2 = 1;
|
||||
samplesInYLog2 = 1;
|
||||
break;
|
||||
case 8: // 4x2
|
||||
samplesInXLog2 = 2;
|
||||
samplesInYLog2 = 1;
|
||||
break;
|
||||
case 16: // 4x4
|
||||
samplesInXLog2 = 2;
|
||||
samplesInYLog2 = 2;
|
||||
break;
|
||||
case 32: // 8x4
|
||||
samplesInXLog2 = 3;
|
||||
samplesInYLog2 = 2;
|
||||
break;
|
||||
case 64: // 8x8
|
||||
samplesInXLog2 = 3;
|
||||
samplesInYLog2 = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
return (samplesInXLog2, samplesInYLog2);
|
||||
}
|
||||
|
||||
private static ITexture Create2DLayerView(TextureView from, int layer, GAL.Format? format = null)
|
||||
{
|
||||
var target = from.Info.Target switch
|
||||
{
|
||||
Target.Texture1DArray => Target.Texture1D,
|
||||
Target.Texture2DArray => Target.Texture2D,
|
||||
Target.Texture2DMultisampleArray => Target.Texture2DMultisample,
|
||||
_ => from.Info.Target
|
||||
};
|
||||
|
||||
var info = new TextureCreateInfo(
|
||||
from.Info.Width,
|
||||
from.Info.Height,
|
||||
from.Info.Depth,
|
||||
1,
|
||||
from.Info.Samples,
|
||||
from.Info.BlockWidth,
|
||||
from.Info.BlockHeight,
|
||||
from.Info.BytesPerPixel,
|
||||
format ?? from.Info.Format,
|
||||
from.Info.DepthStencilMode,
|
||||
target,
|
||||
from.Info.SwizzleR,
|
||||
from.Info.SwizzleG,
|
||||
from.Info.SwizzleB,
|
||||
from.Info.SwizzleA);
|
||||
|
||||
return from.CreateView(info, layer, 0);
|
||||
}
|
||||
|
||||
private static GAL.Format GetFormat(int bytesPerPixel)
|
||||
{
|
||||
return bytesPerPixel switch
|
||||
{
|
||||
1 => GAL.Format.R8Uint,
|
||||
2 => GAL.Format.R16Uint,
|
||||
4 => GAL.Format.R32Uint,
|
||||
8 => GAL.Format.R32G32Uint,
|
||||
16 => GAL.Format.R32G32B32A32Uint,
|
||||
_ => throw new ArgumentException($"Invalid bytes per pixel {bytesPerPixel}.")
|
||||
};
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_programColorBlitClearAlpha.Dispose();
|
||||
_programColorBlit.Dispose();
|
||||
_programColorClear.Dispose();
|
||||
_programStrideChange.Dispose();
|
||||
_programColorCopyBetweenMsNonMs.Dispose();
|
||||
_samplerNearest.Dispose();
|
||||
_samplerLinear.Dispose();
|
||||
_pipeline.Dispose();
|
||||
|
@ -3,6 +3,8 @@ using Ryujinx.Graphics.Shader;
|
||||
using Silk.NET.Vulkan;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
@ -697,6 +699,18 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
SignalStateChange();
|
||||
}
|
||||
|
||||
public void Specialize<T>(in T data) where T : unmanaged
|
||||
{
|
||||
var dataSpan = MemoryMarshal.AsBytes(MemoryMarshal.CreateReadOnlySpan(ref Unsafe.AsRef(in data), 1));
|
||||
|
||||
if (!dataSpan.SequenceEqual(_newState.SpecializationData.Span))
|
||||
{
|
||||
_newState.SpecializationData = new SpecData(dataSpan);
|
||||
|
||||
SignalStateChange();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void SignalAttachmentChange()
|
||||
{
|
||||
}
|
||||
@ -1188,14 +1202,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
}
|
||||
}
|
||||
|
||||
var subpassDependency = new SubpassDependency(
|
||||
0,
|
||||
0,
|
||||
PipelineStageFlags.PipelineStageAllGraphicsBit,
|
||||
PipelineStageFlags.PipelineStageAllGraphicsBit,
|
||||
AccessFlags.AccessMemoryReadBit | AccessFlags.AccessMemoryWriteBit | AccessFlags.AccessColorAttachmentWriteBit,
|
||||
AccessFlags.AccessMemoryReadBit | AccessFlags.AccessMemoryWriteBit | AccessFlags.AccessShaderReadBit,
|
||||
0);
|
||||
var subpassDependency = PipelineConverter.CreateSubpassDependency();
|
||||
|
||||
fixed (AttachmentDescription* pAttachmentDescs = attachmentDescs)
|
||||
{
|
||||
|
@ -6,6 +6,9 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
static class PipelineConverter
|
||||
{
|
||||
private const AccessFlags SubpassSrcAccessMask = AccessFlags.AccessMemoryReadBit | AccessFlags.AccessMemoryWriteBit | AccessFlags.AccessColorAttachmentWriteBit;
|
||||
private const AccessFlags SubpassDstAccessMask = AccessFlags.AccessMemoryReadBit | AccessFlags.AccessMemoryWriteBit | AccessFlags.AccessShaderReadBit;
|
||||
|
||||
public static unsafe DisposableRenderPass ToRenderPass(this ProgramPipelineState state, VulkanRenderer gd, Device device)
|
||||
{
|
||||
const int MaxAttachments = Constants.MaxRenderTargets + 1;
|
||||
@ -100,14 +103,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
}
|
||||
}
|
||||
|
||||
var subpassDependency = new SubpassDependency(
|
||||
0,
|
||||
0,
|
||||
PipelineStageFlags.PipelineStageAllGraphicsBit,
|
||||
PipelineStageFlags.PipelineStageAllGraphicsBit,
|
||||
AccessFlags.AccessMemoryReadBit | AccessFlags.AccessMemoryWriteBit,
|
||||
AccessFlags.AccessMemoryReadBit | AccessFlags.AccessMemoryWriteBit,
|
||||
0);
|
||||
var subpassDependency = CreateSubpassDependency();
|
||||
|
||||
fixed (AttachmentDescription* pAttachmentDescs = attachmentDescs)
|
||||
{
|
||||
@ -128,6 +124,32 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
}
|
||||
}
|
||||
|
||||
public static SubpassDependency CreateSubpassDependency()
|
||||
{
|
||||
return new SubpassDependency(
|
||||
0,
|
||||
0,
|
||||
PipelineStageFlags.PipelineStageAllGraphicsBit,
|
||||
PipelineStageFlags.PipelineStageAllGraphicsBit,
|
||||
SubpassSrcAccessMask,
|
||||
SubpassDstAccessMask,
|
||||
0);
|
||||
}
|
||||
|
||||
public unsafe static SubpassDependency2 CreateSubpassDependency2()
|
||||
{
|
||||
return new SubpassDependency2(
|
||||
StructureType.SubpassDependency2,
|
||||
null,
|
||||
0,
|
||||
0,
|
||||
PipelineStageFlags.PipelineStageAllGraphicsBit,
|
||||
PipelineStageFlags.PipelineStageAllGraphicsBit,
|
||||
SubpassSrcAccessMask,
|
||||
SubpassDstAccessMask,
|
||||
0);
|
||||
}
|
||||
|
||||
public static PipelineState ToVulkanPipelineState(this ProgramPipelineState state, VulkanRenderer gd)
|
||||
{
|
||||
PipelineState pipeline = new PipelineState();
|
||||
|
@ -81,237 +81,214 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
set => Internal.Id5 = (Internal.Id5 & 0xFFFFFFFF) | ((ulong)(uint)BitConverter.SingleToInt32Bits(value) << 32);
|
||||
}
|
||||
|
||||
public float BlendConstantR
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle((int)((Internal.Id6 >> 0) & 0xFFFFFFFF));
|
||||
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFF00000000) | ((ulong)(uint)BitConverter.SingleToInt32Bits(value) << 0);
|
||||
}
|
||||
|
||||
public float BlendConstantG
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle((int)((Internal.Id6 >> 32) & 0xFFFFFFFF));
|
||||
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFF) | ((ulong)(uint)BitConverter.SingleToInt32Bits(value) << 32);
|
||||
}
|
||||
|
||||
public float BlendConstantB
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle((int)((Internal.Id7 >> 0) & 0xFFFFFFFF));
|
||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFF00000000) | ((ulong)(uint)BitConverter.SingleToInt32Bits(value) << 0);
|
||||
}
|
||||
|
||||
public float BlendConstantA
|
||||
{
|
||||
get => BitConverter.Int32BitsToSingle((int)((Internal.Id7 >> 32) & 0xFFFFFFFF));
|
||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFF) | ((ulong)(uint)BitConverter.SingleToInt32Bits(value) << 32);
|
||||
}
|
||||
|
||||
public PolygonMode PolygonMode
|
||||
{
|
||||
get => (PolygonMode)((Internal.Id8 >> 0) & 0x3FFFFFFF);
|
||||
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFC0000000) | ((ulong)value << 0);
|
||||
get => (PolygonMode)((Internal.Id6 >> 0) & 0x3FFFFFFF);
|
||||
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFC0000000) | ((ulong)value << 0);
|
||||
}
|
||||
|
||||
public uint StagesCount
|
||||
{
|
||||
get => (byte)((Internal.Id8 >> 30) & 0xFF);
|
||||
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFC03FFFFFFF) | ((ulong)value << 30);
|
||||
get => (byte)((Internal.Id6 >> 30) & 0xFF);
|
||||
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFC03FFFFFFF) | ((ulong)value << 30);
|
||||
}
|
||||
|
||||
public uint VertexAttributeDescriptionsCount
|
||||
{
|
||||
get => (byte)((Internal.Id8 >> 38) & 0xFF);
|
||||
set => Internal.Id8 = (Internal.Id8 & 0xFFFFC03FFFFFFFFF) | ((ulong)value << 38);
|
||||
get => (byte)((Internal.Id6 >> 38) & 0xFF);
|
||||
set => Internal.Id6 = (Internal.Id6 & 0xFFFFC03FFFFFFFFF) | ((ulong)value << 38);
|
||||
}
|
||||
|
||||
public uint VertexBindingDescriptionsCount
|
||||
{
|
||||
get => (byte)((Internal.Id8 >> 46) & 0xFF);
|
||||
set => Internal.Id8 = (Internal.Id8 & 0xFFC03FFFFFFFFFFF) | ((ulong)value << 46);
|
||||
get => (byte)((Internal.Id6 >> 46) & 0xFF);
|
||||
set => Internal.Id6 = (Internal.Id6 & 0xFFC03FFFFFFFFFFF) | ((ulong)value << 46);
|
||||
}
|
||||
|
||||
public uint ViewportsCount
|
||||
{
|
||||
get => (byte)((Internal.Id8 >> 54) & 0xFF);
|
||||
set => Internal.Id8 = (Internal.Id8 & 0xC03FFFFFFFFFFFFF) | ((ulong)value << 54);
|
||||
get => (byte)((Internal.Id6 >> 54) & 0xFF);
|
||||
set => Internal.Id6 = (Internal.Id6 & 0xC03FFFFFFFFFFFFF) | ((ulong)value << 54);
|
||||
}
|
||||
|
||||
public uint ScissorsCount
|
||||
{
|
||||
get => (byte)((Internal.Id9 >> 0) & 0xFF);
|
||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFF00) | ((ulong)value << 0);
|
||||
get => (byte)((Internal.Id7 >> 0) & 0xFF);
|
||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFFFFFFFF00) | ((ulong)value << 0);
|
||||
}
|
||||
|
||||
public uint ColorBlendAttachmentStateCount
|
||||
{
|
||||
get => (byte)((Internal.Id9 >> 8) & 0xFF);
|
||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFF00FF) | ((ulong)value << 8);
|
||||
get => (byte)((Internal.Id7 >> 8) & 0xFF);
|
||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFFFFFF00FF) | ((ulong)value << 8);
|
||||
}
|
||||
|
||||
public PrimitiveTopology Topology
|
||||
{
|
||||
get => (PrimitiveTopology)((Internal.Id9 >> 16) & 0xF);
|
||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFF0FFFF) | ((ulong)value << 16);
|
||||
get => (PrimitiveTopology)((Internal.Id7 >> 16) & 0xF);
|
||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFFFFF0FFFF) | ((ulong)value << 16);
|
||||
}
|
||||
|
||||
public LogicOp LogicOp
|
||||
{
|
||||
get => (LogicOp)((Internal.Id9 >> 20) & 0xF);
|
||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFF0FFFFF) | ((ulong)value << 20);
|
||||
get => (LogicOp)((Internal.Id7 >> 20) & 0xF);
|
||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFFFF0FFFFF) | ((ulong)value << 20);
|
||||
}
|
||||
|
||||
public CompareOp DepthCompareOp
|
||||
{
|
||||
get => (CompareOp)((Internal.Id9 >> 24) & 0x7);
|
||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFF8FFFFFF) | ((ulong)value << 24);
|
||||
get => (CompareOp)((Internal.Id7 >> 24) & 0x7);
|
||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFFF8FFFFFF) | ((ulong)value << 24);
|
||||
}
|
||||
|
||||
public StencilOp StencilFrontFailOp
|
||||
{
|
||||
get => (StencilOp)((Internal.Id9 >> 27) & 0x7);
|
||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFC7FFFFFF) | ((ulong)value << 27);
|
||||
get => (StencilOp)((Internal.Id7 >> 27) & 0x7);
|
||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFFC7FFFFFF) | ((ulong)value << 27);
|
||||
}
|
||||
|
||||
public StencilOp StencilFrontPassOp
|
||||
{
|
||||
get => (StencilOp)((Internal.Id9 >> 30) & 0x7);
|
||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFE3FFFFFFF) | ((ulong)value << 30);
|
||||
get => (StencilOp)((Internal.Id7 >> 30) & 0x7);
|
||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFE3FFFFFFF) | ((ulong)value << 30);
|
||||
}
|
||||
|
||||
public StencilOp StencilFrontDepthFailOp
|
||||
{
|
||||
get => (StencilOp)((Internal.Id9 >> 33) & 0x7);
|
||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFF1FFFFFFFF) | ((ulong)value << 33);
|
||||
get => (StencilOp)((Internal.Id7 >> 33) & 0x7);
|
||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFF1FFFFFFFF) | ((ulong)value << 33);
|
||||
}
|
||||
|
||||
public CompareOp StencilFrontCompareOp
|
||||
{
|
||||
get => (CompareOp)((Internal.Id9 >> 36) & 0x7);
|
||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFF8FFFFFFFFF) | ((ulong)value << 36);
|
||||
get => (CompareOp)((Internal.Id7 >> 36) & 0x7);
|
||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFF8FFFFFFFFF) | ((ulong)value << 36);
|
||||
}
|
||||
|
||||
public StencilOp StencilBackFailOp
|
||||
{
|
||||
get => (StencilOp)((Internal.Id9 >> 39) & 0x7);
|
||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFC7FFFFFFFFF) | ((ulong)value << 39);
|
||||
get => (StencilOp)((Internal.Id7 >> 39) & 0x7);
|
||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFC7FFFFFFFFF) | ((ulong)value << 39);
|
||||
}
|
||||
|
||||
public StencilOp StencilBackPassOp
|
||||
{
|
||||
get => (StencilOp)((Internal.Id9 >> 42) & 0x7);
|
||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFFE3FFFFFFFFFF) | ((ulong)value << 42);
|
||||
get => (StencilOp)((Internal.Id7 >> 42) & 0x7);
|
||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFE3FFFFFFFFFF) | ((ulong)value << 42);
|
||||
}
|
||||
|
||||
public StencilOp StencilBackDepthFailOp
|
||||
{
|
||||
get => (StencilOp)((Internal.Id9 >> 45) & 0x7);
|
||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFF1FFFFFFFFFFF) | ((ulong)value << 45);
|
||||
get => (StencilOp)((Internal.Id7 >> 45) & 0x7);
|
||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFF1FFFFFFFFFFF) | ((ulong)value << 45);
|
||||
}
|
||||
|
||||
public CompareOp StencilBackCompareOp
|
||||
{
|
||||
get => (CompareOp)((Internal.Id9 >> 48) & 0x7);
|
||||
set => Internal.Id9 = (Internal.Id9 & 0xFFF8FFFFFFFFFFFF) | ((ulong)value << 48);
|
||||
get => (CompareOp)((Internal.Id7 >> 48) & 0x7);
|
||||
set => Internal.Id7 = (Internal.Id7 & 0xFFF8FFFFFFFFFFFF) | ((ulong)value << 48);
|
||||
}
|
||||
|
||||
public CullModeFlags CullMode
|
||||
{
|
||||
get => (CullModeFlags)((Internal.Id9 >> 51) & 0x3);
|
||||
set => Internal.Id9 = (Internal.Id9 & 0xFFE7FFFFFFFFFFFF) | ((ulong)value << 51);
|
||||
get => (CullModeFlags)((Internal.Id7 >> 51) & 0x3);
|
||||
set => Internal.Id7 = (Internal.Id7 & 0xFFE7FFFFFFFFFFFF) | ((ulong)value << 51);
|
||||
}
|
||||
|
||||
public bool PrimitiveRestartEnable
|
||||
{
|
||||
get => ((Internal.Id9 >> 53) & 0x1) != 0UL;
|
||||
set => Internal.Id9 = (Internal.Id9 & 0xFFDFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 53);
|
||||
get => ((Internal.Id7 >> 53) & 0x1) != 0UL;
|
||||
set => Internal.Id7 = (Internal.Id7 & 0xFFDFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 53);
|
||||
}
|
||||
|
||||
public bool DepthClampEnable
|
||||
{
|
||||
get => ((Internal.Id9 >> 54) & 0x1) != 0UL;
|
||||
set => Internal.Id9 = (Internal.Id9 & 0xFFBFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 54);
|
||||
get => ((Internal.Id7 >> 54) & 0x1) != 0UL;
|
||||
set => Internal.Id7 = (Internal.Id7 & 0xFFBFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 54);
|
||||
}
|
||||
|
||||
public bool RasterizerDiscardEnable
|
||||
{
|
||||
get => ((Internal.Id9 >> 55) & 0x1) != 0UL;
|
||||
set => Internal.Id9 = (Internal.Id9 & 0xFF7FFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 55);
|
||||
get => ((Internal.Id7 >> 55) & 0x1) != 0UL;
|
||||
set => Internal.Id7 = (Internal.Id7 & 0xFF7FFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 55);
|
||||
}
|
||||
|
||||
public FrontFace FrontFace
|
||||
{
|
||||
get => (FrontFace)((Internal.Id9 >> 56) & 0x1);
|
||||
set => Internal.Id9 = (Internal.Id9 & 0xFEFFFFFFFFFFFFFF) | ((ulong)value << 56);
|
||||
get => (FrontFace)((Internal.Id7 >> 56) & 0x1);
|
||||
set => Internal.Id7 = (Internal.Id7 & 0xFEFFFFFFFFFFFFFF) | ((ulong)value << 56);
|
||||
}
|
||||
|
||||
public bool DepthBiasEnable
|
||||
{
|
||||
get => ((Internal.Id9 >> 57) & 0x1) != 0UL;
|
||||
set => Internal.Id9 = (Internal.Id9 & 0xFDFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 57);
|
||||
get => ((Internal.Id7 >> 57) & 0x1) != 0UL;
|
||||
set => Internal.Id7 = (Internal.Id7 & 0xFDFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 57);
|
||||
}
|
||||
|
||||
public bool DepthTestEnable
|
||||
{
|
||||
get => ((Internal.Id9 >> 58) & 0x1) != 0UL;
|
||||
set => Internal.Id9 = (Internal.Id9 & 0xFBFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 58);
|
||||
get => ((Internal.Id7 >> 58) & 0x1) != 0UL;
|
||||
set => Internal.Id7 = (Internal.Id7 & 0xFBFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 58);
|
||||
}
|
||||
|
||||
public bool DepthWriteEnable
|
||||
{
|
||||
get => ((Internal.Id9 >> 59) & 0x1) != 0UL;
|
||||
set => Internal.Id9 = (Internal.Id9 & 0xF7FFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 59);
|
||||
get => ((Internal.Id7 >> 59) & 0x1) != 0UL;
|
||||
set => Internal.Id7 = (Internal.Id7 & 0xF7FFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 59);
|
||||
}
|
||||
|
||||
public bool DepthBoundsTestEnable
|
||||
{
|
||||
get => ((Internal.Id9 >> 60) & 0x1) != 0UL;
|
||||
set => Internal.Id9 = (Internal.Id9 & 0xEFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 60);
|
||||
get => ((Internal.Id7 >> 60) & 0x1) != 0UL;
|
||||
set => Internal.Id7 = (Internal.Id7 & 0xEFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 60);
|
||||
}
|
||||
|
||||
public bool StencilTestEnable
|
||||
{
|
||||
get => ((Internal.Id9 >> 61) & 0x1) != 0UL;
|
||||
set => Internal.Id9 = (Internal.Id9 & 0xDFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 61);
|
||||
get => ((Internal.Id7 >> 61) & 0x1) != 0UL;
|
||||
set => Internal.Id7 = (Internal.Id7 & 0xDFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 61);
|
||||
}
|
||||
|
||||
public bool LogicOpEnable
|
||||
{
|
||||
get => ((Internal.Id9 >> 62) & 0x1) != 0UL;
|
||||
set => Internal.Id9 = (Internal.Id9 & 0xBFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 62);
|
||||
get => ((Internal.Id7 >> 62) & 0x1) != 0UL;
|
||||
set => Internal.Id7 = (Internal.Id7 & 0xBFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 62);
|
||||
}
|
||||
|
||||
public bool HasDepthStencil
|
||||
{
|
||||
get => ((Internal.Id9 >> 63) & 0x1) != 0UL;
|
||||
set => Internal.Id9 = (Internal.Id9 & 0x7FFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 63);
|
||||
get => ((Internal.Id7 >> 63) & 0x1) != 0UL;
|
||||
set => Internal.Id7 = (Internal.Id7 & 0x7FFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 63);
|
||||
}
|
||||
|
||||
public uint PatchControlPoints
|
||||
{
|
||||
get => (uint)((Internal.Id10 >> 0) & 0xFFFFFFFF);
|
||||
set => Internal.Id10 = (Internal.Id10 & 0xFFFFFFFF00000000) | ((ulong)value << 0);
|
||||
get => (uint)((Internal.Id8 >> 0) & 0xFFFFFFFF);
|
||||
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFF00000000) | ((ulong)value << 0);
|
||||
}
|
||||
|
||||
public uint SamplesCount
|
||||
{
|
||||
get => (uint)((Internal.Id10 >> 32) & 0xFFFFFFFF);
|
||||
set => Internal.Id10 = (Internal.Id10 & 0xFFFFFFFF) | ((ulong)value << 32);
|
||||
get => (uint)((Internal.Id8 >> 32) & 0xFFFFFFFF);
|
||||
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFF) | ((ulong)value << 32);
|
||||
}
|
||||
|
||||
public bool AlphaToCoverageEnable
|
||||
{
|
||||
get => ((Internal.Id11 >> 0) & 0x1) != 0UL;
|
||||
set => Internal.Id11 = (Internal.Id11 & 0xFFFFFFFFFFFFFFFE) | ((value ? 1UL : 0UL) << 0);
|
||||
get => ((Internal.Id9 >> 0) & 0x1) != 0UL;
|
||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFFE) | ((value ? 1UL : 0UL) << 0);
|
||||
}
|
||||
|
||||
public bool AlphaToOneEnable
|
||||
{
|
||||
get => ((Internal.Id11 >> 1) & 0x1) != 0UL;
|
||||
set => Internal.Id11 = (Internal.Id11 & 0xFFFFFFFFFFFFFFFD) | ((value ? 1UL : 0UL) << 1);
|
||||
get => ((Internal.Id9 >> 1) & 0x1) != 0UL;
|
||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFFD) | ((value ? 1UL : 0UL) << 1);
|
||||
}
|
||||
|
||||
public NativeArray<PipelineShaderStageCreateInfo> Stages;
|
||||
public NativeArray<PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT> StageRequiredSubgroupSizes;
|
||||
public PipelineLayout PipelineLayout;
|
||||
public SpecData SpecializationData;
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
@ -334,7 +311,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
ShaderCollection program,
|
||||
PipelineCache cache)
|
||||
{
|
||||
if (program.TryGetComputePipeline(out var pipeline))
|
||||
if (program.TryGetComputePipeline(ref SpecializationData, out var pipeline))
|
||||
{
|
||||
return pipeline;
|
||||
}
|
||||
@ -354,20 +331,36 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
Pipeline pipelineHandle = default;
|
||||
|
||||
gd.Api.CreateComputePipelines(device, cache, 1, &pipelineCreateInfo, null, &pipelineHandle).ThrowOnError();
|
||||
bool hasSpec = program.SpecDescriptions != null;
|
||||
|
||||
var desc = hasSpec ? program.SpecDescriptions[0] : SpecDescription.Empty;
|
||||
|
||||
if (hasSpec && SpecializationData.Length < (int)desc.Info.DataSize)
|
||||
{
|
||||
throw new InvalidOperationException("Specialization data size does not match description");
|
||||
}
|
||||
|
||||
fixed (SpecializationInfo* info = &desc.Info)
|
||||
fixed (SpecializationMapEntry* map = desc.Map)
|
||||
fixed (byte* data = SpecializationData.Span)
|
||||
{
|
||||
if (hasSpec)
|
||||
{
|
||||
info->PMapEntries = map;
|
||||
info->PData = data;
|
||||
pipelineCreateInfo.Stage.PSpecializationInfo = info;
|
||||
}
|
||||
|
||||
gd.Api.CreateComputePipelines(device, cache, 1, &pipelineCreateInfo, null, &pipelineHandle).ThrowOnError();
|
||||
}
|
||||
|
||||
pipeline = new Auto<DisposablePipeline>(new DisposablePipeline(gd.Api, device, pipelineHandle));
|
||||
|
||||
program.AddComputePipeline(pipeline);
|
||||
program.AddComputePipeline(ref SpecializationData, pipeline);
|
||||
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
public unsafe void DestroyComputePipeline(ShaderCollection program)
|
||||
{
|
||||
program.RemoveComputePipeline();
|
||||
}
|
||||
|
||||
public unsafe Auto<DisposablePipeline> CreateGraphicsPipeline(
|
||||
VulkanRenderer gd,
|
||||
Device device,
|
||||
@ -493,11 +486,6 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
PAttachments = pColorBlendAttachmentState
|
||||
};
|
||||
|
||||
colorBlendState.BlendConstants[0] = BlendConstantR;
|
||||
colorBlendState.BlendConstants[1] = BlendConstantG;
|
||||
colorBlendState.BlendConstants[2] = BlendConstantB;
|
||||
colorBlendState.BlendConstants[3] = BlendConstantA;
|
||||
|
||||
bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState;
|
||||
int dynamicStatesCount = supportsExtDynamicState ? 9 : 8;
|
||||
|
||||
|
@ -21,15 +21,13 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
public ulong Id8;
|
||||
public ulong Id9;
|
||||
public ulong Id10;
|
||||
public ulong Id11;
|
||||
|
||||
private uint VertexAttributeDescriptionsCount => (byte)((Id8 >> 38) & 0xFF);
|
||||
private uint VertexBindingDescriptionsCount => (byte)((Id8 >> 46) & 0xFF);
|
||||
private uint ViewportsCount => (byte)((Id8 >> 54) & 0xFF);
|
||||
private uint ScissorsCount => (byte)((Id9 >> 0) & 0xFF);
|
||||
private uint ColorBlendAttachmentStateCount => (byte)((Id9 >> 8) & 0xFF);
|
||||
private bool HasDepthStencil => ((Id9 >> 63) & 0x1) != 0UL;
|
||||
private uint VertexAttributeDescriptionsCount => (byte)((Id6 >> 38) & 0xFF);
|
||||
private uint VertexBindingDescriptionsCount => (byte)((Id6 >> 46) & 0xFF);
|
||||
private uint ViewportsCount => (byte)((Id6 >> 54) & 0xFF);
|
||||
private uint ScissorsCount => (byte)((Id7 >> 0) & 0xFF);
|
||||
private uint ColorBlendAttachmentStateCount => (byte)((Id7 >> 8) & 0xFF);
|
||||
private bool HasDepthStencil => ((Id7 >> 63) & 0x1) != 0UL;
|
||||
|
||||
public Array32<VertexInputAttributeDescription> VertexAttributeDescriptions;
|
||||
public Array33<VertexInputBindingDescription> VertexBindingDescriptions;
|
||||
@ -47,7 +45,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
if (!Unsafe.As<ulong, Vector256<byte>>(ref Id0).Equals(Unsafe.As<ulong, Vector256<byte>>(ref other.Id0)) ||
|
||||
!Unsafe.As<ulong, Vector256<byte>>(ref Id4).Equals(Unsafe.As<ulong, Vector256<byte>>(ref other.Id4)) ||
|
||||
!Unsafe.As<ulong, Vector256<byte>>(ref Id8).Equals(Unsafe.As<ulong, Vector256<byte>>(ref other.Id8)))
|
||||
!Unsafe.As<ulong, Vector128<byte>>(ref Id8).Equals(Unsafe.As<ulong, Vector128<byte>>(ref other.Id8)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -91,9 +89,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
Id6 * 23 ^
|
||||
Id7 * 23 ^
|
||||
Id8 * 23 ^
|
||||
Id9 * 23 ^
|
||||
Id10 * 23 ^
|
||||
Id11 * 23;
|
||||
Id9 * 23;
|
||||
|
||||
for (int i = 0; i < (int)VertexAttributeDescriptionsCount; i++)
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
|
@ -26,6 +26,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
public ProgramLinkStatus LinkStatus { get; private set; }
|
||||
|
||||
public readonly SpecDescription[] SpecDescriptions;
|
||||
|
||||
public bool IsLinked
|
||||
{
|
||||
get
|
||||
@ -40,7 +42,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
}
|
||||
|
||||
private HashTableSlim<PipelineUid, Auto<DisposablePipeline>> _graphicsPipelineCache;
|
||||
private Auto<DisposablePipeline> _computePipeline;
|
||||
private HashTableSlim<SpecData, Auto<DisposablePipeline>> _computePipelineCache;
|
||||
|
||||
private VulkanRenderer _gd;
|
||||
private Device _device;
|
||||
@ -52,17 +54,24 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
private Task _compileTask;
|
||||
private bool _firstBackgroundUse;
|
||||
|
||||
public ShaderCollection(VulkanRenderer gd, Device device, ShaderSource[] shaders, bool isMinimal = false)
|
||||
public ShaderCollection(VulkanRenderer gd, Device device, ShaderSource[] shaders, SpecDescription[] specDescription = null, bool isMinimal = false)
|
||||
{
|
||||
_gd = gd;
|
||||
_device = device;
|
||||
|
||||
if (specDescription != null && specDescription.Length != shaders.Length)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(specDescription)} array length must match {nameof(shaders)} array if provided");
|
||||
}
|
||||
|
||||
gd.Shaders.Add(this);
|
||||
|
||||
var internalShaders = new Shader[shaders.Length];
|
||||
|
||||
_infos = new PipelineShaderStageCreateInfo[shaders.Length];
|
||||
|
||||
SpecDescriptions = specDescription;
|
||||
|
||||
LinkStatus = ProgramLinkStatus.Incomplete;
|
||||
|
||||
uint stages = 0;
|
||||
@ -314,14 +323,9 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
return null;
|
||||
}
|
||||
|
||||
public void AddComputePipeline(Auto<DisposablePipeline> pipeline)
|
||||
public void AddComputePipeline(ref SpecData key, Auto<DisposablePipeline> pipeline)
|
||||
{
|
||||
_computePipeline = pipeline;
|
||||
}
|
||||
|
||||
public void RemoveComputePipeline()
|
||||
{
|
||||
_computePipeline = null;
|
||||
(_computePipelineCache ??= new()).Add(ref key, pipeline);
|
||||
}
|
||||
|
||||
public void AddGraphicsPipeline(ref PipelineUid key, Auto<DisposablePipeline> pipeline)
|
||||
@ -329,10 +333,20 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
(_graphicsPipelineCache ??= new()).Add(ref key, pipeline);
|
||||
}
|
||||
|
||||
public bool TryGetComputePipeline(out Auto<DisposablePipeline> pipeline)
|
||||
public bool TryGetComputePipeline(ref SpecData key, out Auto<DisposablePipeline> pipeline)
|
||||
{
|
||||
pipeline = _computePipeline;
|
||||
return pipeline != null;
|
||||
if (_computePipelineCache == null)
|
||||
{
|
||||
pipeline = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_computePipelineCache.TryGetValue(ref key, out pipeline))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGetGraphicsPipeline(ref PipelineUid key, out Auto<DisposablePipeline> pipeline)
|
||||
@ -390,7 +404,14 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
}
|
||||
}
|
||||
|
||||
_computePipeline?.Dispose();
|
||||
if (_computePipelineCache != null)
|
||||
{
|
||||
foreach (Auto<DisposablePipeline> pipeline in _computePipelineCache.Values)
|
||||
{
|
||||
pipeline.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
if (_dummyRenderPass.Value.Handle != 0)
|
||||
{
|
||||
_dummyRenderPass.Dispose();
|
||||
|
89
Ryujinx.Graphics.Vulkan/Shaders/ColorCopyBetweenMsNonMs.comp
Normal file
89
Ryujinx.Graphics.Vulkan/Shaders/ColorCopyBetweenMsNonMs.comp
Normal file
@ -0,0 +1,89 @@
|
||||
#version 450 core
|
||||
|
||||
// +ve for MsToNonMs, -ve for reverse
|
||||
layout (constant_id = 0) const int convType = 0;
|
||||
|
||||
layout (std140, binding = 0) uniform sample_counts_log2_in
|
||||
{
|
||||
ivec4 sample_counts_log2;
|
||||
};
|
||||
|
||||
#define R8_ID 1
|
||||
#define R16_ID 2
|
||||
#define R32_ID 4
|
||||
#define RG32_ID 8
|
||||
#define RGBA32_ID 16
|
||||
|
||||
#define R8_TYPE r8ui
|
||||
#define R16_TYPE r16ui
|
||||
#define R32_TYPE r32ui
|
||||
#define RG32_TYPE rg32ui
|
||||
#define RGBA32_TYPE rgba32ui
|
||||
|
||||
#define DECLARE_BINDINGS(type) layout (set = 3, binding = 0, type##_TYPE) uniform uimage2DMS dstMS ## type; \
|
||||
layout (set = 3, binding = 0, type##_TYPE) uniform uimage2D dst ## type;
|
||||
|
||||
#define CASE_SIZE(type) case type##_ID: imageSz = imageSize(dst ## type); break;
|
||||
|
||||
#define CASE_CONVERT(type) case type##_ID: imageStore(dst ## type, ivec2(coords), texelFetch(srcMS, shiftedCoords, sampleIdx)); break; \
|
||||
case -type##_ID: imageStore(dstMS ## type, shiftedCoords, sampleIdx, texelFetch(src, ivec2(coords), 0)); break;
|
||||
|
||||
// src tex
|
||||
layout (set = 2, binding = 0) uniform usampler2DMS srcMS;
|
||||
layout (set = 2, binding = 0) uniform usampler2D src;
|
||||
|
||||
// dst img
|
||||
DECLARE_BINDINGS(R8)
|
||||
DECLARE_BINDINGS(R16)
|
||||
DECLARE_BINDINGS(R32)
|
||||
DECLARE_BINDINGS(RG32)
|
||||
DECLARE_BINDINGS(RGBA32)
|
||||
|
||||
layout (local_size_x = 32, local_size_y = 32, local_size_z = 1) in;
|
||||
|
||||
void main()
|
||||
{
|
||||
uvec2 coords = gl_GlobalInvocationID.xy;
|
||||
|
||||
ivec2 imageSz = ivec2(0, 0);
|
||||
|
||||
switch (convType)
|
||||
{
|
||||
case 0: break;
|
||||
CASE_SIZE(R8 )
|
||||
CASE_SIZE(R16 )
|
||||
CASE_SIZE(R32 )
|
||||
CASE_SIZE(RG32 )
|
||||
CASE_SIZE(RGBA32)
|
||||
default:
|
||||
imageSz = textureSize(src, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (int(coords.x) >= imageSz.x || int(coords.y) >= imageSz.y)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int deltaX = sample_counts_log2.x - sample_counts_log2.z;
|
||||
int deltaY = sample_counts_log2.y - sample_counts_log2.w;
|
||||
int samplesInXLog2 = sample_counts_log2.z;
|
||||
int samplesInYLog2 = sample_counts_log2.w;
|
||||
int samplesInX = 1 << samplesInXLog2;
|
||||
int samplesInY = 1 << samplesInYLog2;
|
||||
int sampleIdx = ((int(coords.x) >> deltaX) & (samplesInX - 1)) | (((int(coords.y) >> deltaY) & (samplesInY - 1)) << samplesInXLog2);
|
||||
|
||||
samplesInXLog2 = sample_counts_log2.x;
|
||||
samplesInYLog2 = sample_counts_log2.y;
|
||||
|
||||
ivec2 shiftedCoords = ivec2(int(coords.x) >> samplesInXLog2, int(coords.y) >> samplesInYLog2);
|
||||
|
||||
switch (convType)
|
||||
{
|
||||
CASE_CONVERT(R8 )
|
||||
CASE_CONVERT(R16 )
|
||||
CASE_CONVERT(R32 )
|
||||
CASE_CONVERT(RG32 )
|
||||
CASE_CONVERT(RGBA32)
|
||||
}
|
||||
}
|
@ -551,5 +551,324 @@ namespace Ryujinx.Graphics.Vulkan.Shaders
|
||||
0x21, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00,
|
||||
0x35, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00,
|
||||
};
|
||||
|
||||
public static readonly byte[] ColorCopyBetweenMsNonMs = new byte[]
|
||||
{
|
||||
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, 0x2D, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
|
||||
0x1B, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x31, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
|
||||
0x32, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4C, 0x53, 0x4C,
|
||||
0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x06, 0x00, 0x05, 0x00, 0x00, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
|
||||
0x10, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
|
||||
0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0xC2, 0x01, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E,
|
||||
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x47,
|
||||
0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x49, 0x6E, 0x76, 0x6F, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x49,
|
||||
0x44, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x63, 0x6F, 0x6E, 0x76,
|
||||
0x54, 0x79, 0x70, 0x65, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||
0x64, 0x73, 0x74, 0x52, 0x38, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00,
|
||||
0x64, 0x73, 0x74, 0x52, 0x31, 0x36, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x2D, 0x00, 0x00, 0x00,
|
||||
0x64, 0x73, 0x74, 0x52, 0x33, 0x32, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x33, 0x00, 0x00, 0x00,
|
||||
0x64, 0x73, 0x74, 0x52, 0x47, 0x33, 0x32, 0x00, 0x05, 0x00, 0x05, 0x00, 0x39, 0x00, 0x00, 0x00,
|
||||
0x64, 0x73, 0x74, 0x52, 0x47, 0x42, 0x41, 0x33, 0x32, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
|
||||
0x40, 0x00, 0x00, 0x00, 0x73, 0x72, 0x63, 0x00, 0x05, 0x00, 0x08, 0x00, 0x60, 0x00, 0x00, 0x00,
|
||||
0x73, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x5F, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x73, 0x5F, 0x6C, 0x6F,
|
||||
0x67, 0x32, 0x5F, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x60, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x73, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x5F, 0x63, 0x6F, 0x75, 0x6E, 0x74,
|
||||
0x73, 0x5F, 0x6C, 0x6F, 0x67, 0x32, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x62, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0xB3, 0x00, 0x00, 0x00, 0x73, 0x72, 0x63, 0x4D,
|
||||
0x53, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0xBD, 0x00, 0x00, 0x00, 0x64, 0x73, 0x74, 0x4D,
|
||||
0x53, 0x52, 0x38, 0x00, 0x05, 0x00, 0x05, 0x00, 0xD2, 0x00, 0x00, 0x00, 0x64, 0x73, 0x74, 0x4D,
|
||||
0x53, 0x52, 0x31, 0x36, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0xE7, 0x00, 0x00, 0x00,
|
||||
0x64, 0x73, 0x74, 0x4D, 0x53, 0x52, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00,
|
||||
0xFC, 0x00, 0x00, 0x00, 0x64, 0x73, 0x74, 0x4D, 0x53, 0x52, 0x47, 0x33, 0x32, 0x00, 0x00, 0x00,
|
||||
0x05, 0x00, 0x05, 0x00, 0x11, 0x01, 0x00, 0x00, 0x64, 0x73, 0x74, 0x4D, 0x53, 0x52, 0x47, 0x42,
|
||||
0x41, 0x33, 0x32, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,
|
||||
0x1C, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x21, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x33, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x33, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x39, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x39, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x40, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x40, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x60, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x62, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x62, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xB3, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xB3, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xBD, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xBD, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xD2, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xD2, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xE7, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xE7, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x11, 0x01, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x11, 0x01, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1D, 0x01, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,
|
||||
0x19, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
|
||||
0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00,
|
||||
0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00,
|
||||
0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||
0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||
0x0F, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||
0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||
0x14, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x32, 0x00, 0x04, 0x00,
|
||||
0x0F, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00,
|
||||
0x1F, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
|
||||
0x20, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00,
|
||||
0x3B, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x19, 0x00, 0x09, 0x00, 0x25, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x26, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x25, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x2C, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x2C, 0x00, 0x00, 0x00,
|
||||
0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0x31, 0x00, 0x00, 0x00,
|
||||
0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
|
||||
0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00,
|
||||
0x32, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00,
|
||||
0x37, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00,
|
||||
0x20, 0x00, 0x04, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
|
||||
0x3B, 0x00, 0x04, 0x00, 0x38, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x19, 0x00, 0x09, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x03, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x00, 0x00,
|
||||
0x20, 0x00, 0x04, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00,
|
||||
0x3B, 0x00, 0x04, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x14, 0x00, 0x02, 0x00, 0x46, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||
0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||
0x53, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x5F, 0x00, 0x00, 0x00,
|
||||
0x0F, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x03, 0x00, 0x60, 0x00, 0x00, 0x00,
|
||||
0x5F, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x60, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x63, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x0F, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6D, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x03, 0x00, 0xB1, 0x00, 0x00, 0x00,
|
||||
0xB0, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xB1, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0xB2, 0x00, 0x00, 0x00, 0xB3, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0xBB, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xBC, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0xBC, 0x00, 0x00, 0x00,
|
||||
0xBD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0xD0, 0x00, 0x00, 0x00,
|
||||
0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
|
||||
0xD1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00,
|
||||
0xD1, 0x00, 0x00, 0x00, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00,
|
||||
0xE5, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||
0x20, 0x00, 0x04, 0x00, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE5, 0x00, 0x00, 0x00,
|
||||
0x3B, 0x00, 0x04, 0x00, 0xE6, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x19, 0x00, 0x09, 0x00, 0xFA, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x23, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFA, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0xFB, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0x0F, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0F, 0x01, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x10, 0x01, 0x00, 0x00,
|
||||
0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||
0x1C, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x06, 0x00, 0x0A, 0x00, 0x00, 0x00,
|
||||
0x1D, 0x01, 0x00, 0x00, 0x1C, 0x01, 0x00, 0x00, 0x1C, 0x01, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00,
|
||||
0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0xF7, 0x00, 0x03, 0x00,
|
||||
0x1E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFB, 0x00, 0x03, 0x00, 0x47, 0x00, 0x00, 0x00,
|
||||
0x1F, 0x01, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x1F, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||
0x0A, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x07, 0x00,
|
||||
0x07, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xF7, 0x00, 0x03, 0x00, 0x1D, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xFB, 0x00, 0x0F, 0x00, 0x15, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00,
|
||||
0xF8, 0x00, 0x02, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x3E, 0x00, 0x00, 0x00,
|
||||
0x41, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x3D, 0x00, 0x00, 0x00,
|
||||
0x42, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x67, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||
0x43, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00,
|
||||
0x1D, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x16, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00,
|
||||
0x1D, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x17, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||
0x1F, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x68, 0x00, 0x04, 0x00,
|
||||
0x10, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00,
|
||||
0x1D, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x18, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||
0x25, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x68, 0x00, 0x04, 0x00,
|
||||
0x10, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00,
|
||||
0x1D, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||
0x2B, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x68, 0x00, 0x04, 0x00,
|
||||
0x10, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00,
|
||||
0x1D, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||
0x31, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x68, 0x00, 0x04, 0x00,
|
||||
0x10, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00,
|
||||
0x1D, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||
0x37, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x68, 0x00, 0x04, 0x00,
|
||||
0x10, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00,
|
||||
0x1D, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x1D, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x11, 0x00,
|
||||
0x10, 0x00, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
|
||||
0x14, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
|
||||
0x29, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
|
||||
0x35, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00,
|
||||
0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00,
|
||||
0x4A, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x00, 0x00,
|
||||
0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x05, 0x00, 0x46, 0x00, 0x00, 0x00,
|
||||
0x4F, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x00, 0x00, 0xA8, 0x00, 0x04, 0x00,
|
||||
0x46, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x00, 0x00, 0xF7, 0x00, 0x03, 0x00,
|
||||
0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x04, 0x00, 0x50, 0x00, 0x00, 0x00,
|
||||
0x51, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x51, 0x00, 0x00, 0x00,
|
||||
0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00,
|
||||
0x55, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
|
||||
0x2C, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x05, 0x00, 0x46, 0x00, 0x00, 0x00,
|
||||
0x59, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00,
|
||||
0x52, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x52, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x07, 0x00,
|
||||
0x46, 0x00, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00,
|
||||
0x59, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0xF7, 0x00, 0x03, 0x00, 0x5C, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x04, 0x00, 0x5A, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00,
|
||||
0x5C, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x5B, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00,
|
||||
0x1E, 0x01, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00,
|
||||
0x63, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
|
||||
0x47, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00,
|
||||
0x64, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x63, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00,
|
||||
0x62, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||
0x0F, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00,
|
||||
0x0F, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
|
||||
0x41, 0x00, 0x06, 0x00, 0x63, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00,
|
||||
0x13, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||
0x6C, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x63, 0x00, 0x00, 0x00,
|
||||
0x6E, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x6D, 0x00, 0x00, 0x00,
|
||||
0x3D, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x00, 0x00,
|
||||
0x82, 0x00, 0x05, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00,
|
||||
0x6F, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x05, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x7A, 0x00, 0x00, 0x00,
|
||||
0x78, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x05, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||
0x7D, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x05, 0x00,
|
||||
0x0F, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00,
|
||||
0x82, 0x00, 0x05, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x7A, 0x00, 0x00, 0x00,
|
||||
0x78, 0x00, 0x00, 0x00, 0xC7, 0x00, 0x05, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00,
|
||||
0x83, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||
0x88, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00,
|
||||
0x0F, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x05, 0x00,
|
||||
0x0F, 0x00, 0x00, 0x00, 0x8B, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
|
||||
0x82, 0x00, 0x05, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00,
|
||||
0x78, 0x00, 0x00, 0x00, 0xC7, 0x00, 0x05, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x00,
|
||||
0x8B, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x05, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||
0x90, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0xC5, 0x00, 0x05, 0x00,
|
||||
0x0F, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00,
|
||||
0xC3, 0x00, 0x05, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00,
|
||||
0x65, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x05, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x00,
|
||||
0x89, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||
0xA1, 0x00, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x00, 0xF7, 0x00, 0x03, 0x00,
|
||||
0xAC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFB, 0x00, 0x17, 0x00, 0x15, 0x00, 0x00, 0x00,
|
||||
0xAC, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xA3, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF,
|
||||
0xA5, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xA6, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF,
|
||||
0xA7, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF,
|
||||
0xA9, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xAA, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xAB, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0xA2, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||
0x1F, 0x00, 0x00, 0x00, 0xAD, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00,
|
||||
0x10, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||
0xB1, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0xB3, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00,
|
||||
0xB0, 0x00, 0x00, 0x00, 0xB7, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00,
|
||||
0xB8, 0x00, 0x00, 0x00, 0xB9, 0x00, 0x00, 0x00, 0xB7, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00,
|
||||
0x40, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x63, 0x00, 0x04, 0x00, 0xAD, 0x00, 0x00, 0x00,
|
||||
0xAF, 0x00, 0x00, 0x00, 0xB9, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0xAC, 0x00, 0x00, 0x00,
|
||||
0xF8, 0x00, 0x02, 0x00, 0xA3, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0xBB, 0x00, 0x00, 0x00,
|
||||
0xBE, 0x00, 0x00, 0x00, 0xBD, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x3E, 0x00, 0x00, 0x00,
|
||||
0xC1, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||
0xC3, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x3D, 0x00, 0x00, 0x00,
|
||||
0xC4, 0x00, 0x00, 0x00, 0xC1, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0xB8, 0x00, 0x00, 0x00,
|
||||
0xC5, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x13, 0x00, 0x00, 0x00, 0x63, 0x00, 0x06, 0x00, 0xBE, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00,
|
||||
0xC5, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00,
|
||||
0xAC, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0xA4, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||
0x25, 0x00, 0x00, 0x00, 0xC7, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00,
|
||||
0x10, 0x00, 0x00, 0x00, 0xC9, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||
0xB1, 0x00, 0x00, 0x00, 0xCA, 0x00, 0x00, 0x00, 0xB3, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00,
|
||||
0xB0, 0x00, 0x00, 0x00, 0xCD, 0x00, 0x00, 0x00, 0xCA, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00,
|
||||
0xB8, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00, 0xCD, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00,
|
||||
0x40, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x63, 0x00, 0x04, 0x00, 0xC7, 0x00, 0x00, 0x00,
|
||||
0xC9, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0xAC, 0x00, 0x00, 0x00,
|
||||
0xF8, 0x00, 0x02, 0x00, 0xA5, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0xD0, 0x00, 0x00, 0x00,
|
||||
0xD3, 0x00, 0x00, 0x00, 0xD2, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x3E, 0x00, 0x00, 0x00,
|
||||
0xD6, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||
0xD8, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x3D, 0x00, 0x00, 0x00,
|
||||
0xD9, 0x00, 0x00, 0x00, 0xD6, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0xB8, 0x00, 0x00, 0x00,
|
||||
0xDA, 0x00, 0x00, 0x00, 0xD9, 0x00, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x13, 0x00, 0x00, 0x00, 0x63, 0x00, 0x06, 0x00, 0xD3, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00,
|
||||
0xDA, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00,
|
||||
0xAC, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0xA6, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||
0x2B, 0x00, 0x00, 0x00, 0xDC, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00,
|
||||
0x10, 0x00, 0x00, 0x00, 0xDE, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||
0xB1, 0x00, 0x00, 0x00, 0xDF, 0x00, 0x00, 0x00, 0xB3, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00,
|
||||
0xB0, 0x00, 0x00, 0x00, 0xE2, 0x00, 0x00, 0x00, 0xDF, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00,
|
||||
0xB8, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, 0xE2, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00,
|
||||
0x40, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x63, 0x00, 0x04, 0x00, 0xDC, 0x00, 0x00, 0x00,
|
||||
0xDE, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0xAC, 0x00, 0x00, 0x00,
|
||||
0xF8, 0x00, 0x02, 0x00, 0xA7, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0xE5, 0x00, 0x00, 0x00,
|
||||
0xE8, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x3E, 0x00, 0x00, 0x00,
|
||||
0xEB, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||
0xED, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x3D, 0x00, 0x00, 0x00,
|
||||
0xEE, 0x00, 0x00, 0x00, 0xEB, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0xB8, 0x00, 0x00, 0x00,
|
||||
0xEF, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xED, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x13, 0x00, 0x00, 0x00, 0x63, 0x00, 0x06, 0x00, 0xE8, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00,
|
||||
0xEF, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00,
|
||||
0xAC, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0xA8, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||
0x31, 0x00, 0x00, 0x00, 0xF1, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00,
|
||||
0x10, 0x00, 0x00, 0x00, 0xF3, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||
0xB1, 0x00, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x00, 0xB3, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00,
|
||||
0xB0, 0x00, 0x00, 0x00, 0xF7, 0x00, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00,
|
||||
0xB8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF7, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00,
|
||||
0x40, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x63, 0x00, 0x04, 0x00, 0xF1, 0x00, 0x00, 0x00,
|
||||
0xF3, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0xAC, 0x00, 0x00, 0x00,
|
||||
0xF8, 0x00, 0x02, 0x00, 0xA9, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0xFA, 0x00, 0x00, 0x00,
|
||||
0xFD, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x3E, 0x00, 0x00, 0x00,
|
||||
0x00, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||
0x02, 0x01, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x3D, 0x00, 0x00, 0x00,
|
||||
0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0xB8, 0x00, 0x00, 0x00,
|
||||
0x04, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x13, 0x00, 0x00, 0x00, 0x63, 0x00, 0x06, 0x00, 0xFD, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00,
|
||||
0x04, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00,
|
||||
0xAC, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0xAA, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||
0x37, 0x00, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00,
|
||||
0x10, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||
0xB1, 0x00, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0xB3, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00,
|
||||
0xB0, 0x00, 0x00, 0x00, 0x0C, 0x01, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00,
|
||||
0xB8, 0x00, 0x00, 0x00, 0x0D, 0x01, 0x00, 0x00, 0x0C, 0x01, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00,
|
||||
0x40, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x63, 0x00, 0x04, 0x00, 0x06, 0x01, 0x00, 0x00,
|
||||
0x08, 0x01, 0x00, 0x00, 0x0D, 0x01, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0xAC, 0x00, 0x00, 0x00,
|
||||
0xF8, 0x00, 0x02, 0x00, 0xAB, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x0F, 0x01, 0x00, 0x00,
|
||||
0x12, 0x01, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x3E, 0x00, 0x00, 0x00,
|
||||
0x15, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||
0x17, 0x01, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x3D, 0x00, 0x00, 0x00,
|
||||
0x18, 0x01, 0x00, 0x00, 0x15, 0x01, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0xB8, 0x00, 0x00, 0x00,
|
||||
0x19, 0x01, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x17, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x13, 0x00, 0x00, 0x00, 0x63, 0x00, 0x06, 0x00, 0x12, 0x01, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00,
|
||||
0x19, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00,
|
||||
0xAC, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0xAC, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00,
|
||||
0x1E, 0x01, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x1E, 0x01, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00,
|
||||
0x38, 0x00, 0x01, 0x00,
|
||||
};
|
||||
}
|
||||
}
|
103
Ryujinx.Graphics.Vulkan/SpecInfo.cs
Normal file
103
Ryujinx.Graphics.Vulkan/SpecInfo.cs
Normal file
@ -0,0 +1,103 @@
|
||||
using Silk.NET.Vulkan;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
public enum SpecConstType
|
||||
{
|
||||
Bool32,
|
||||
Int16,
|
||||
Int32,
|
||||
Int64,
|
||||
Float16,
|
||||
Float32,
|
||||
Float64
|
||||
}
|
||||
|
||||
sealed class SpecDescription
|
||||
{
|
||||
public readonly SpecializationInfo Info;
|
||||
public readonly SpecializationMapEntry[] Map;
|
||||
|
||||
// For mapping a simple packed struct or single entry
|
||||
public SpecDescription(params (uint Id, SpecConstType Type)[] description)
|
||||
{
|
||||
int count = description.Length;
|
||||
Map = new SpecializationMapEntry[count];
|
||||
|
||||
uint structSize = 0;
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
var typeSize = SizeOf(description[i].Type);
|
||||
Map[i] = new SpecializationMapEntry(description[i].Id, structSize, typeSize);
|
||||
structSize += typeSize;
|
||||
}
|
||||
|
||||
Info = new SpecializationInfo()
|
||||
{
|
||||
DataSize = structSize,
|
||||
MapEntryCount = (uint)count
|
||||
};
|
||||
}
|
||||
|
||||
// For advanced mapping with overlapping or staggered fields
|
||||
public SpecDescription(SpecializationMapEntry[] map)
|
||||
{
|
||||
int count = map.Length;
|
||||
Map = map;
|
||||
|
||||
uint structSize = 0;
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
structSize = Math.Max(structSize, map[i].Offset + (uint)map[i].Size);
|
||||
}
|
||||
|
||||
Info = new SpecializationInfo()
|
||||
{
|
||||
DataSize = structSize,
|
||||
MapEntryCount = (uint)map.Length
|
||||
};
|
||||
}
|
||||
|
||||
private static uint SizeOf(SpecConstType type) => type switch
|
||||
{
|
||||
SpecConstType.Int16 or SpecConstType.Float16 => 2,
|
||||
SpecConstType.Bool32 or SpecConstType.Int32 or SpecConstType.Float32 => 4,
|
||||
SpecConstType.Int64 or SpecConstType.Float64 => 8,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(type))
|
||||
};
|
||||
|
||||
private SpecDescription()
|
||||
{
|
||||
Info = new();
|
||||
}
|
||||
|
||||
public static readonly SpecDescription Empty = new();
|
||||
}
|
||||
|
||||
readonly struct SpecData : IRefEquatable<SpecData>
|
||||
{
|
||||
private readonly byte[] _data;
|
||||
private readonly int _hash;
|
||||
|
||||
public int Length => _data.Length;
|
||||
public ReadOnlySpan<byte> Span => _data.AsSpan();
|
||||
public override int GetHashCode() => _hash;
|
||||
|
||||
public SpecData(ReadOnlySpan<byte> data)
|
||||
{
|
||||
_data = new byte[data.Length];
|
||||
data.CopyTo(_data);
|
||||
|
||||
var hc = new HashCode();
|
||||
hc.AddBytes(data);
|
||||
_hash = hc.ToHashCode();
|
||||
}
|
||||
|
||||
public override bool Equals(object obj) => obj is SpecData other && Equals(other);
|
||||
public bool Equals(ref SpecData other) => _data.AsSpan().SequenceEqual(other._data);
|
||||
}
|
||||
}
|
@ -355,5 +355,122 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
dstLayers,
|
||||
levels);
|
||||
}
|
||||
|
||||
public unsafe static void ResolveDepthStencil(
|
||||
VulkanRenderer gd,
|
||||
Device device,
|
||||
CommandBufferScoped cbs,
|
||||
TextureView src,
|
||||
TextureView dst)
|
||||
{
|
||||
var dsAttachmentReference = new AttachmentReference2(StructureType.AttachmentReference2, null, 0, ImageLayout.General);
|
||||
var dsResolveAttachmentReference = new AttachmentReference2(StructureType.AttachmentReference2, null, 1, ImageLayout.General);
|
||||
|
||||
var subpassDsResolve = new SubpassDescriptionDepthStencilResolve()
|
||||
{
|
||||
SType = StructureType.SubpassDescriptionDepthStencilResolve,
|
||||
PDepthStencilResolveAttachment = &dsResolveAttachmentReference,
|
||||
DepthResolveMode = ResolveModeFlags.ResolveModeSampleZeroBit,
|
||||
StencilResolveMode = ResolveModeFlags.ResolveModeSampleZeroBit
|
||||
};
|
||||
|
||||
var subpass = new SubpassDescription2()
|
||||
{
|
||||
SType = StructureType.SubpassDescription2,
|
||||
PipelineBindPoint = PipelineBindPoint.Graphics,
|
||||
PDepthStencilAttachment = &dsAttachmentReference,
|
||||
PNext = &subpassDsResolve
|
||||
};
|
||||
|
||||
AttachmentDescription2[] attachmentDescs = new AttachmentDescription2[2];
|
||||
|
||||
attachmentDescs[0] = new AttachmentDescription2(
|
||||
StructureType.AttachmentDescription2,
|
||||
null,
|
||||
0,
|
||||
src.VkFormat,
|
||||
TextureStorage.ConvertToSampleCountFlags((uint)src.Info.Samples),
|
||||
AttachmentLoadOp.Load,
|
||||
AttachmentStoreOp.Store,
|
||||
AttachmentLoadOp.Load,
|
||||
AttachmentStoreOp.Store,
|
||||
ImageLayout.General,
|
||||
ImageLayout.General);
|
||||
|
||||
attachmentDescs[1] = new AttachmentDescription2(
|
||||
StructureType.AttachmentDescription2,
|
||||
null,
|
||||
0,
|
||||
dst.VkFormat,
|
||||
TextureStorage.ConvertToSampleCountFlags((uint)dst.Info.Samples),
|
||||
AttachmentLoadOp.Load,
|
||||
AttachmentStoreOp.Store,
|
||||
AttachmentLoadOp.Load,
|
||||
AttachmentStoreOp.Store,
|
||||
ImageLayout.General,
|
||||
ImageLayout.General);
|
||||
|
||||
var subpassDependency = PipelineConverter.CreateSubpassDependency2();
|
||||
|
||||
fixed (AttachmentDescription2* pAttachmentDescs = attachmentDescs)
|
||||
{
|
||||
var renderPassCreateInfo = new RenderPassCreateInfo2()
|
||||
{
|
||||
SType = StructureType.RenderPassCreateInfo2,
|
||||
PAttachments = pAttachmentDescs,
|
||||
AttachmentCount = (uint)attachmentDescs.Length,
|
||||
PSubpasses = &subpass,
|
||||
SubpassCount = 1,
|
||||
PDependencies = &subpassDependency,
|
||||
DependencyCount = 1
|
||||
};
|
||||
|
||||
gd.Api.CreateRenderPass2(device, renderPassCreateInfo, null, out var renderPass).ThrowOnError();
|
||||
|
||||
using var rp = new Auto<DisposableRenderPass>(new DisposableRenderPass(gd.Api, device, renderPass));
|
||||
|
||||
ImageView* attachments = stackalloc ImageView[2];
|
||||
|
||||
var srcView = src.GetImageViewForAttachment();
|
||||
var dstView = dst.GetImageViewForAttachment();
|
||||
|
||||
attachments[0] = srcView.Get(cbs).Value;
|
||||
attachments[1] = dstView.Get(cbs).Value;
|
||||
|
||||
var framebufferCreateInfo = new FramebufferCreateInfo()
|
||||
{
|
||||
SType = StructureType.FramebufferCreateInfo,
|
||||
RenderPass = rp.Get(cbs).Value,
|
||||
AttachmentCount = 2,
|
||||
PAttachments = attachments,
|
||||
Width = (uint)src.Width,
|
||||
Height = (uint)src.Height,
|
||||
Layers = (uint)src.Layers
|
||||
};
|
||||
|
||||
gd.Api.CreateFramebuffer(device, framebufferCreateInfo, null, out var framebuffer).ThrowOnError();
|
||||
using var fb = new Auto<DisposableFramebuffer>(new DisposableFramebuffer(gd.Api, device, framebuffer), null, new[] { srcView, dstView });
|
||||
|
||||
var renderArea = new Rect2D(null, new Extent2D((uint)src.Info.Width, (uint)src.Info.Height));
|
||||
var clearValue = new ClearValue();
|
||||
|
||||
var renderPassBeginInfo = new RenderPassBeginInfo()
|
||||
{
|
||||
SType = StructureType.RenderPassBeginInfo,
|
||||
RenderPass = rp.Get(cbs).Value,
|
||||
Framebuffer = fb.Get(cbs).Value,
|
||||
RenderArea = renderArea,
|
||||
PClearValues = &clearValue,
|
||||
ClearValueCount = 1
|
||||
};
|
||||
|
||||
// The resolve operation happens at the end of the subpass, so let's just do a begin/end
|
||||
// to resolve the depth-stencil texture.
|
||||
// TODO: Do speculative resolve and part of the same render pass as the draw to avoid
|
||||
// ending the current render pass?
|
||||
gd.Api.CmdBeginRenderPass(cbs.CommandBuffer, renderPassBeginInfo, SubpassContents.Inline);
|
||||
gd.Api.CmdEndRenderPass(cbs.CommandBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -169,12 +169,15 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
var srcImage = src.GetImage().Get(cbs).Value;
|
||||
var dstImage = dst.GetImage().Get(cbs).Value;
|
||||
|
||||
if (src.Info.Target.IsMultisample())
|
||||
if (!dst.Info.Target.IsMultisample() && Info.Target.IsMultisample())
|
||||
{
|
||||
int depth = Math.Min(src.Info.Depth, dst.Info.Depth - firstLayer);
|
||||
int levels = Math.Min(src.Info.Levels, dst.Info.Levels - firstLevel);
|
||||
|
||||
CopyMSToNonMS(_gd, cbs, src, dst, srcImage, dstImage, 0, firstLayer, 0, firstLevel, depth, levels);
|
||||
int layers = Math.Min(Info.GetLayers(), dst.Info.GetLayers() - firstLayer);
|
||||
_gd.HelperShader.CopyMSToNonMS(_gd, cbs, src, dst, 0, firstLayer, layers);
|
||||
}
|
||||
else if (dst.Info.Target.IsMultisample() && !Info.Target.IsMultisample())
|
||||
{
|
||||
int layers = Math.Min(Info.GetLayers(), dst.Info.GetLayers() - firstLayer);
|
||||
_gd.HelperShader.CopyNonMSToMS(_gd, cbs, src, dst, 0, firstLayer, layers);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -213,9 +216,13 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
var srcImage = src.GetImage().Get(cbs).Value;
|
||||
var dstImage = dst.GetImage().Get(cbs).Value;
|
||||
|
||||
if (src.Info.Target.IsMultisample())
|
||||
if (!dst.Info.Target.IsMultisample() && Info.Target.IsMultisample())
|
||||
{
|
||||
CopyMSToNonMS(_gd, cbs, src, dst, srcImage, dstImage, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1);
|
||||
_gd.HelperShader.CopyMSToNonMS(_gd, cbs, src, dst, srcLayer, dstLayer, 1);
|
||||
}
|
||||
else if (dst.Info.Target.IsMultisample() && !Info.Target.IsMultisample())
|
||||
{
|
||||
_gd.HelperShader.CopyNonMSToMS(_gd, cbs, src, dst, srcLayer, dstLayer, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -239,142 +246,6 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
}
|
||||
}
|
||||
|
||||
private static void CopyMSToNonMS(
|
||||
VulkanRenderer gd,
|
||||
CommandBufferScoped cbs,
|
||||
TextureView src,
|
||||
TextureView dst,
|
||||
Image srcImage,
|
||||
Image dstImage,
|
||||
int srcLayer,
|
||||
int dstLayer,
|
||||
int srcLevel,
|
||||
int dstLevel,
|
||||
int layers,
|
||||
int levels)
|
||||
{
|
||||
bool differentFormats = src.Info.Format != dst.Info.Format;
|
||||
|
||||
var target = src.Info.Target switch
|
||||
{
|
||||
Target.Texture2D => Target.Texture2DMultisample,
|
||||
Target.Texture2DArray => Target.Texture2DMultisampleArray,
|
||||
Target.Texture2DMultisampleArray => Target.Texture2DArray,
|
||||
_ => Target.Texture2D
|
||||
};
|
||||
|
||||
var intermmediateTarget = differentFormats ? dst.Info.Target : target;
|
||||
using var intermmediate = CreateIntermmediateTexture(gd, src, ref dst._info, intermmediateTarget, layers, levels);
|
||||
var intermmediateImage = intermmediate.GetImage().Get(cbs).Value;
|
||||
|
||||
if (differentFormats)
|
||||
{
|
||||
// If the formats are different, the resolve would perform format conversion.
|
||||
// So we need yet another intermmediate texture and do a copy to reinterpret the
|
||||
// data into the correct (destination) format, without doing any sort of conversion.
|
||||
using var intermmediate2 = CreateIntermmediateTexture(gd, src, ref src._info, target, layers, levels);
|
||||
var intermmediate2Image = intermmediate2.GetImage().Get(cbs).Value;
|
||||
|
||||
TextureCopy.Copy(
|
||||
gd.Api,
|
||||
cbs.CommandBuffer,
|
||||
srcImage,
|
||||
intermmediate2Image,
|
||||
src.Info,
|
||||
intermmediate2.Info,
|
||||
src.FirstLayer,
|
||||
0,
|
||||
src.FirstLevel,
|
||||
0,
|
||||
srcLayer,
|
||||
0,
|
||||
srcLevel,
|
||||
0,
|
||||
layers,
|
||||
levels);
|
||||
|
||||
TextureCopy.Copy(
|
||||
gd.Api,
|
||||
cbs.CommandBuffer,
|
||||
intermmediate2Image,
|
||||
intermmediateImage,
|
||||
intermmediate2.Info,
|
||||
intermmediate.Info,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
layers,
|
||||
levels);
|
||||
}
|
||||
else
|
||||
{
|
||||
TextureCopy.Copy(
|
||||
gd.Api,
|
||||
cbs.CommandBuffer,
|
||||
srcImage,
|
||||
intermmediateImage,
|
||||
src.Info,
|
||||
intermmediate.Info,
|
||||
src.FirstLayer,
|
||||
0,
|
||||
src.FirstLevel,
|
||||
0,
|
||||
srcLayer,
|
||||
0,
|
||||
srcLevel,
|
||||
0,
|
||||
layers,
|
||||
levels);
|
||||
}
|
||||
|
||||
var srcRegion = new Extents2D(0, 0, src.Width, src.Height);
|
||||
var dstRegion = new Extents2D(0, 0, dst.Width, dst.Height);
|
||||
|
||||
TextureCopy.Blit(
|
||||
gd.Api,
|
||||
cbs.CommandBuffer,
|
||||
intermmediateImage,
|
||||
dstImage,
|
||||
intermmediate.Info,
|
||||
dst.Info,
|
||||
srcRegion,
|
||||
dstRegion,
|
||||
0,
|
||||
dst.FirstLevel + dstLevel,
|
||||
0,
|
||||
dst.FirstLayer + dstLayer,
|
||||
layers,
|
||||
levels,
|
||||
true,
|
||||
ImageAspectFlags.ImageAspectColorBit,
|
||||
ImageAspectFlags.ImageAspectColorBit);
|
||||
}
|
||||
|
||||
private static TextureView CreateIntermmediateTexture(VulkanRenderer gd, TextureView src, ref TextureCreateInfo formatInfo, Target target, int depth, int levels)
|
||||
{
|
||||
return gd.CreateTextureView(new GAL.TextureCreateInfo(
|
||||
src.Width,
|
||||
src.Height,
|
||||
depth,
|
||||
levels,
|
||||
1,
|
||||
formatInfo.BlockWidth,
|
||||
formatInfo.BlockHeight,
|
||||
formatInfo.BytesPerPixel,
|
||||
formatInfo.Format,
|
||||
DepthStencilMode.Depth,
|
||||
target,
|
||||
SwizzleComponent.Red,
|
||||
SwizzleComponent.Green,
|
||||
SwizzleComponent.Blue,
|
||||
SwizzleComponent.Alpha), 1f);
|
||||
}
|
||||
|
||||
public void CopyTo(ITexture destination, Extents2D srcRegion, Extents2D dstRegion, bool linearFilter)
|
||||
{
|
||||
var dst = (TextureView)destination;
|
||||
@ -422,23 +293,32 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
src.Height == dst.Height &&
|
||||
src.VkFormat == dst.VkFormat)
|
||||
{
|
||||
TextureCopy.Copy(
|
||||
_gd.Api,
|
||||
cbs.CommandBuffer,
|
||||
src.GetImage().Get(cbs).Value,
|
||||
dst.GetImage().Get(cbs).Value,
|
||||
src.Info,
|
||||
dst.Info,
|
||||
src.FirstLayer,
|
||||
dst.FirstLayer,
|
||||
src.FirstLevel,
|
||||
dst.FirstLevel,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
layers,
|
||||
levels);
|
||||
if (src.Info.Samples > 1 && src.Info.Samples != dst.Info.Samples && src.Info.Format.IsDepthOrStencil())
|
||||
{
|
||||
// CmdResolveImage does not support depth-stencil resolve, so we need to use an alternative path
|
||||
// for those textures.
|
||||
TextureCopy.ResolveDepthStencil(_gd, _device, cbs, src, dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
TextureCopy.Copy(
|
||||
_gd.Api,
|
||||
cbs.CommandBuffer,
|
||||
src.GetImage().Get(cbs).Value,
|
||||
dst.GetImage().Get(cbs).Value,
|
||||
src.Info,
|
||||
dst.Info,
|
||||
src.FirstLayer,
|
||||
dst.FirstLayer,
|
||||
src.FirstLevel,
|
||||
dst.FirstLevel,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
layers,
|
||||
levels);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Silk.NET.Vulkan;
|
||||
@ -53,7 +53,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
"VUID-VkSubpassDependency-srcSubpass-00867"
|
||||
};
|
||||
|
||||
internal static Instance CreateInstance(Vk api, GraphicsDebugLevel logLevel, string[] requiredExtensions, out ExtDebugReport debugReport, out DebugReportCallbackEXT debugReportCallback)
|
||||
internal static Instance CreateInstance(Vk api, GraphicsDebugLevel logLevel, string[] requiredExtensions, out ExtDebugUtils debugUtils, out DebugUtilsMessengerEXT debugUtilsMessenger)
|
||||
{
|
||||
var enabledLayers = new List<string>();
|
||||
|
||||
@ -89,7 +89,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
AddAvailableLayer("VK_LAYER_KHRONOS_validation");
|
||||
}
|
||||
|
||||
var enabledExtensions = requiredExtensions.Append(ExtDebugReport.ExtensionName).ToArray();
|
||||
var enabledExtensions = requiredExtensions.Append(ExtDebugUtils.ExtensionName).ToArray();
|
||||
|
||||
var appName = Marshal.StringToHGlobalAnsi(AppName);
|
||||
|
||||
@ -139,22 +139,18 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
Marshal.FreeHGlobal(ppEnabledLayers[i]);
|
||||
}
|
||||
|
||||
CreateDebugCallbacks(api, logLevel, instance, out debugReport, out debugReportCallback);
|
||||
CreateDebugMessenger(api, logLevel, instance, out debugUtils, out debugUtilsMessenger);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
private unsafe static uint DebugReport(
|
||||
uint flags,
|
||||
DebugReportObjectTypeEXT objectType,
|
||||
ulong @object,
|
||||
nuint location,
|
||||
int messageCode,
|
||||
byte* layerPrefix,
|
||||
byte* message,
|
||||
void* userData)
|
||||
private unsafe static uint DebugMessenger(
|
||||
DebugUtilsMessageSeverityFlagsEXT messageSeverity,
|
||||
DebugUtilsMessageTypeFlagsEXT messageTypes,
|
||||
DebugUtilsMessengerCallbackDataEXT* pCallbackData,
|
||||
void* pUserData)
|
||||
{
|
||||
var msg = Marshal.PtrToStringAnsi((IntPtr)message);
|
||||
var msg = Marshal.PtrToStringAnsi((IntPtr)pCallbackData->PMessage);
|
||||
|
||||
foreach (string excludedMessagePart in _excludedMessages)
|
||||
{
|
||||
@ -164,26 +160,20 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
}
|
||||
}
|
||||
|
||||
DebugReportFlagsEXT debugFlags = (DebugReportFlagsEXT)flags;
|
||||
|
||||
if (debugFlags.HasFlag(DebugReportFlagsEXT.DebugReportErrorBitExt))
|
||||
if (messageSeverity.HasFlag(DebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityErrorBitExt))
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Gpu, msg);
|
||||
//throw new Exception(msg);
|
||||
}
|
||||
else if (debugFlags.HasFlag(DebugReportFlagsEXT.DebugReportWarningBitExt))
|
||||
else if (messageSeverity.HasFlag(DebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityWarningBitExt))
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Gpu, msg);
|
||||
}
|
||||
else if (debugFlags.HasFlag(DebugReportFlagsEXT.DebugReportInformationBitExt))
|
||||
else if (messageSeverity.HasFlag(DebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityInfoBitExt))
|
||||
{
|
||||
Logger.Info?.Print(LogClass.Gpu, msg);
|
||||
}
|
||||
else if (debugFlags.HasFlag(DebugReportFlagsEXT.DebugReportPerformanceWarningBitExt))
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Gpu, msg);
|
||||
}
|
||||
else
|
||||
else // if (messageSeverity.HasFlag(DebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityVerboseBitExt))
|
||||
{
|
||||
Logger.Debug?.Print(LogClass.Gpu, msg);
|
||||
}
|
||||
@ -403,6 +393,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
ShaderClipDistance = true,
|
||||
ShaderFloat64 = supportedFeatures.ShaderFloat64,
|
||||
ShaderImageGatherExtended = true,
|
||||
ShaderStorageImageMultisample = supportedFeatures.ShaderStorageImageMultisample,
|
||||
// ShaderStorageImageReadWithoutFormat = true,
|
||||
// ShaderStorageImageWriteWithoutFormat = true,
|
||||
TessellationShader = true,
|
||||
@ -551,46 +542,59 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
return new CommandBufferPool(api, device, queue, queueLock, queueFamilyIndex);
|
||||
}
|
||||
|
||||
internal unsafe static void CreateDebugCallbacks(
|
||||
internal unsafe static void CreateDebugMessenger(
|
||||
Vk api,
|
||||
GraphicsDebugLevel logLevel,
|
||||
Instance instance,
|
||||
out ExtDebugReport debugReport,
|
||||
out DebugReportCallbackEXT debugReportCallback)
|
||||
out ExtDebugUtils debugUtils,
|
||||
out DebugUtilsMessengerEXT debugUtilsMessenger)
|
||||
{
|
||||
debugReport = default;
|
||||
debugUtils = default;
|
||||
|
||||
if (logLevel != GraphicsDebugLevel.None)
|
||||
{
|
||||
if (!api.TryGetInstanceExtension(instance, out debugReport))
|
||||
if (!api.TryGetInstanceExtension(instance, out debugUtils))
|
||||
{
|
||||
debugReportCallback = default;
|
||||
debugUtilsMessenger = default;
|
||||
return;
|
||||
}
|
||||
|
||||
var flags = logLevel switch
|
||||
var filterLogType = logLevel switch
|
||||
{
|
||||
GraphicsDebugLevel.Error => DebugReportFlagsEXT.DebugReportErrorBitExt,
|
||||
GraphicsDebugLevel.Slowdowns => DebugReportFlagsEXT.DebugReportErrorBitExt | DebugReportFlagsEXT.DebugReportPerformanceWarningBitExt,
|
||||
GraphicsDebugLevel.All => DebugReportFlagsEXT.DebugReportInformationBitExt |
|
||||
DebugReportFlagsEXT.DebugReportWarningBitExt |
|
||||
DebugReportFlagsEXT.DebugReportPerformanceWarningBitExt |
|
||||
DebugReportFlagsEXT.DebugReportErrorBitExt |
|
||||
DebugReportFlagsEXT.DebugReportDebugBitExt,
|
||||
GraphicsDebugLevel.Error => DebugUtilsMessageTypeFlagsEXT.DebugUtilsMessageTypeValidationBitExt,
|
||||
GraphicsDebugLevel.Slowdowns => DebugUtilsMessageTypeFlagsEXT.DebugUtilsMessageTypeValidationBitExt |
|
||||
DebugUtilsMessageTypeFlagsEXT.DebugUtilsMessageTypePerformanceBitExt,
|
||||
GraphicsDebugLevel.All => DebugUtilsMessageTypeFlagsEXT.DebugUtilsMessageTypeGeneralBitExt |
|
||||
DebugUtilsMessageTypeFlagsEXT.DebugUtilsMessageTypeValidationBitExt |
|
||||
DebugUtilsMessageTypeFlagsEXT.DebugUtilsMessageTypePerformanceBitExt,
|
||||
_ => throw new ArgumentException($"Invalid log level \"{logLevel}\".")
|
||||
};
|
||||
var debugReportCallbackCreateInfo = new DebugReportCallbackCreateInfoEXT()
|
||||
|
||||
var filterLogSeverity = logLevel switch
|
||||
{
|
||||
SType = StructureType.DebugReportCallbackCreateInfoExt,
|
||||
Flags = flags,
|
||||
PfnCallback = new PfnDebugReportCallbackEXT(DebugReport)
|
||||
GraphicsDebugLevel.Error => DebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityErrorBitExt,
|
||||
GraphicsDebugLevel.Slowdowns => DebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityErrorBitExt |
|
||||
DebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityWarningBitExt,
|
||||
GraphicsDebugLevel.All => DebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityInfoBitExt |
|
||||
DebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityWarningBitExt |
|
||||
DebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityVerboseBitExt |
|
||||
DebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityErrorBitExt,
|
||||
_ => throw new ArgumentException($"Invalid log level \"{logLevel}\".")
|
||||
};
|
||||
|
||||
debugReport.CreateDebugReportCallback(instance, in debugReportCallbackCreateInfo, null, out debugReportCallback).ThrowOnError();
|
||||
var debugUtilsMessengerCreateInfo = new DebugUtilsMessengerCreateInfoEXT()
|
||||
{
|
||||
SType = StructureType.DebugUtilsMessengerCreateInfoExt,
|
||||
MessageType = filterLogType,
|
||||
MessageSeverity = filterLogSeverity,
|
||||
PfnUserCallback = new PfnDebugUtilsMessengerCallbackEXT(DebugMessenger)
|
||||
};
|
||||
|
||||
debugUtils.CreateDebugUtilsMessenger(instance, in debugUtilsMessengerCreateInfo, null, out debugUtilsMessenger).ThrowOnError();
|
||||
}
|
||||
else
|
||||
{
|
||||
debugReportCallback = default;
|
||||
debugUtilsMessenger = default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
internal KhrPushDescriptor PushDescriptorApi { get; private set; }
|
||||
internal ExtTransformFeedback TransformFeedbackApi { get; private set; }
|
||||
internal KhrDrawIndirectCount DrawIndirectCountApi { get; private set; }
|
||||
internal ExtDebugReport DebugReportApi { get; private set; }
|
||||
internal ExtDebugUtils DebugUtilsApi { get; private set; }
|
||||
|
||||
internal uint QueueFamilyIndex { get; private set; }
|
||||
internal Queue Queue { get; private set; }
|
||||
@ -57,7 +57,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
private SyncManager _syncManager;
|
||||
|
||||
private PipelineFull _pipeline;
|
||||
private DebugReportCallbackEXT _debugReportCallback;
|
||||
private DebugUtilsMessengerEXT _debugUtilsMessenger;
|
||||
|
||||
internal HelperShader HelperShader { get; private set; }
|
||||
internal PipelineFull PipelineInternal => _pipeline;
|
||||
@ -237,9 +237,9 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
Api = api;
|
||||
|
||||
_instance = VulkanInitialization.CreateInstance(api, logLevel, _getRequiredExtensions(), out ExtDebugReport debugReport, out _debugReportCallback);
|
||||
_instance = VulkanInitialization.CreateInstance(api, logLevel, _getRequiredExtensions(), out ExtDebugUtils debugUtils, out _debugUtilsMessenger);
|
||||
|
||||
DebugReportApi = debugReport;
|
||||
DebugUtilsApi = debugUtils;
|
||||
|
||||
if (api.TryGetInstanceExtension(_instance, out KhrSurface surfaceApi))
|
||||
{
|
||||
@ -287,9 +287,9 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
}
|
||||
}
|
||||
|
||||
internal ShaderCollection CreateProgramWithMinimalLayout(ShaderSource[] sources)
|
||||
internal ShaderCollection CreateProgramWithMinimalLayout(ShaderSource[] sources, SpecDescription[] specDescription = null)
|
||||
{
|
||||
return new ShaderCollection(this, _device, sources, isMinimal: true);
|
||||
return new ShaderCollection(this, _device, sources, specDescription: specDescription, isMinimal: true);
|
||||
}
|
||||
|
||||
public ISampler CreateSampler(GAL.SamplerCreateInfo info)
|
||||
@ -584,9 +584,9 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
MemoryAllocator.Dispose();
|
||||
|
||||
if (_debugReportCallback.Handle != 0)
|
||||
if (_debugUtilsMessenger.Handle != 0)
|
||||
{
|
||||
DebugReportApi.DestroyDebugReportCallback(_instance, _debugReportCallback, null);
|
||||
DebugUtilsApi.DestroyDebugUtilsMessenger(_instance, _debugUtilsMessenger, null);
|
||||
}
|
||||
|
||||
foreach (var shader in Shaders)
|
||||
|
@ -9,10 +9,10 @@ using LibHac.Tools.FsSystem;
|
||||
using LibHac.Tools.FsSystem.NcaUtils;
|
||||
using LibHac.Tools.Ncm;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using Ryujinx.HLE.Exceptions;
|
||||
using Ryujinx.HLE.HOS.Services.Ssl;
|
||||
using Ryujinx.HLE.HOS.Services.Time;
|
||||
using Ryujinx.HLE.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
@ -293,7 +293,7 @@ namespace Ryujinx.HLE.FileSystem
|
||||
}
|
||||
|
||||
aocStorage = new Nca(_virtualFileSystem.KeySet, ncaFile.Get.AsStorage()).OpenStorage(NcaSectionType.Data, integrityCheckLevel);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -354,7 +354,7 @@ namespace Ryujinx.HLE.FileSystem
|
||||
{
|
||||
if (_contentDictionary.ContainsKey((titleId, contentType)))
|
||||
{
|
||||
return new UInt128(_contentDictionary[(titleId, contentType)]);
|
||||
return UInt128Utils.FromHex(_contentDictionary[(titleId, contentType)]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -407,7 +407,7 @@ namespace Ryujinx.HLE.FileSystem
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
string installedPath = _virtualFileSystem.SwitchPathToSystemPath(locationEntry.ContentPath);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(installedPath))
|
||||
|
@ -10,6 +10,7 @@ using Ryujinx.Audio.Integration;
|
||||
using Ryujinx.Audio.Output;
|
||||
using Ryujinx.Audio.Renderer.Device;
|
||||
using Ryujinx.Audio.Renderer.Server;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using Ryujinx.Cpu;
|
||||
using Ryujinx.Cpu.Jit;
|
||||
using Ryujinx.HLE.FileSystem;
|
||||
@ -35,7 +36,6 @@ using Ryujinx.HLE.HOS.Services.SurfaceFlinger;
|
||||
using Ryujinx.HLE.HOS.Services.Time.Clock;
|
||||
using Ryujinx.HLE.HOS.SystemState;
|
||||
using Ryujinx.HLE.Loaders.Executables;
|
||||
using Ryujinx.HLE.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
@ -201,7 +201,7 @@ namespace Ryujinx.HLE.HOS
|
||||
|
||||
// TODO: use set:sys (and get external clock source id from settings)
|
||||
// TODO: use "time!standard_steady_clock_rtc_update_interval_minutes" and implement a worker thread to be accurate.
|
||||
UInt128 clockSourceId = new UInt128(Guid.NewGuid().ToByteArray());
|
||||
UInt128 clockSourceId = UInt128Utils.CreateRandom();
|
||||
IRtcManager.GetExternalRtcValue(out ulong rtcValue);
|
||||
|
||||
// We assume the rtc is system time.
|
||||
|
@ -1,5 +1,4 @@
|
||||
using LibHac.Account;
|
||||
using Ryujinx.HLE.Utilities;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@ -83,7 +82,7 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
|
||||
|
||||
public readonly UInt128 ToUInt128()
|
||||
{
|
||||
return new UInt128(Low, High);
|
||||
return new UInt128((ulong)High, (ulong)Low);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using Ryujinx.HLE.Utilities;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
|
||||
@ -36,7 +36,7 @@ namespace Ryujinx.HLE.HOS.Services.Mii
|
||||
public static UInt128 GetDeviceId()
|
||||
{
|
||||
// FIXME: call set:sys GetMiiAuthorId
|
||||
return new UInt128("5279754d69694e780000000000000000"); // RyuMiiNx
|
||||
return UInt128Utils.FromHex("5279754d69694e780000000000000000"); // RyuMiiNx
|
||||
}
|
||||
|
||||
public static ReadOnlySpan<byte> Ver3FacelineColorTable => new byte[] { 0, 1, 2, 3, 4, 5 };
|
||||
|
@ -3,7 +3,7 @@ using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Mii.Types
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Size = 0x58)]
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0x58)]
|
||||
struct CharInfo : IStoredData<CharInfo>
|
||||
{
|
||||
public CreateId CreateId;
|
||||
|
@ -1,20 +1,19 @@
|
||||
using Ryujinx.HLE.Utilities;
|
||||
using System;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Mii.Types
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Size = 0x10)]
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0x10)]
|
||||
struct CreateId : IEquatable<CreateId>
|
||||
{
|
||||
public UInt128 Raw;
|
||||
|
||||
public bool IsNull => Raw.IsNull;
|
||||
public bool IsValid => !IsNull && (Raw.High & 0xC0) == 0x80;
|
||||
public bool IsNull => Raw == UInt128.Zero;
|
||||
public bool IsValid => !IsNull && ((Raw >> 64) & 0xC0) == 0x80;
|
||||
|
||||
public CreateId(byte[] data)
|
||||
public CreateId(UInt128 raw)
|
||||
{
|
||||
Raw = new UInt128(data);
|
||||
Raw = raw;
|
||||
}
|
||||
|
||||
public static bool operator ==(CreateId x, CreateId y)
|
||||
|
@ -1,11 +1,12 @@
|
||||
using LibHac.Common;
|
||||
using Ryujinx.HLE.Utilities;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Mii.Types
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = Size)]
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1, Size = Size)]
|
||||
struct StoreData : IStoredData<StoreData>
|
||||
{
|
||||
public const int Size = 0x44;
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Ryujinx.Cpu;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using Ryujinx.Cpu;
|
||||
using Ryujinx.HLE.HOS.Services.Mii.Types;
|
||||
using Ryujinx.HLE.HOS.Services.Time;
|
||||
using Ryujinx.HLE.HOS.Services.Time.Clock;
|
||||
@ -62,7 +63,13 @@ namespace Ryujinx.HLE.HOS.Services.Mii
|
||||
|
||||
public CreateId MakeCreateId()
|
||||
{
|
||||
return new CreateId(Guid.NewGuid().ToByteArray());
|
||||
UInt128 value = UInt128Utils.CreateRandom();
|
||||
|
||||
// Ensure the random ID generated is valid as a create id.
|
||||
value &= ~new UInt128(0xC0, 0);
|
||||
value |= new UInt128(0x80, 0);
|
||||
|
||||
return new CreateId(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using Ryujinx.HLE.HOS.Services.Nifm.StaticService.GeneralService;
|
||||
using Ryujinx.HLE.HOS.Services.Nifm.StaticService.Types;
|
||||
using Ryujinx.HLE.Utilities;
|
||||
using System;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Runtime.CompilerServices;
|
||||
@ -78,7 +78,7 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
|
||||
|
||||
NetworkProfileData networkProfile = new NetworkProfileData
|
||||
{
|
||||
Uuid = new UInt128(Guid.NewGuid().ToByteArray())
|
||||
Uuid = UInt128Utils.CreateRandom()
|
||||
};
|
||||
|
||||
networkProfile.IpSettingData.IpAddressSetting = new IpAddressSetting(interfaceProperties, unicastAddress);
|
||||
|
@ -14,14 +14,7 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService.Types
|
||||
|
||||
public DnsSetting(IPInterfaceProperties interfaceProperties)
|
||||
{
|
||||
try
|
||||
{
|
||||
IsDynamicDnsEnabled = interfaceProperties.IsDynamicDnsEnabled;
|
||||
}
|
||||
catch (PlatformNotSupportedException)
|
||||
{
|
||||
IsDynamicDnsEnabled = false;
|
||||
}
|
||||
IsDynamicDnsEnabled = OperatingSystem.IsWindows() && interfaceProperties.IsDynamicDnsEnabled;
|
||||
|
||||
if (interfaceProperties.DnsAddresses.Count == 0)
|
||||
{
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Net.NetworkInformation;
|
||||
using System;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService.Types
|
||||
@ -14,7 +15,7 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService.Types
|
||||
|
||||
public IpAddressSetting(IPInterfaceProperties interfaceProperties, UnicastIPAddressInformation unicastIPAddressInformation)
|
||||
{
|
||||
IsDhcpEnabled = interfaceProperties.DhcpServerAddresses.Count != 0;
|
||||
IsDhcpEnabled = !OperatingSystem.IsMacOS() && interfaceProperties.DhcpServerAddresses.Count != 0;
|
||||
Address = new IpV4Address(unicastIPAddressInformation.Address);
|
||||
IPv4Mask = new IpV4Address(unicastIPAddressInformation.IPv4Mask);
|
||||
GatewayAddress = new IpV4Address(interfaceProperties.GatewayAddresses[0].Address);
|
||||
|
@ -1,5 +1,5 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.HLE.Utilities;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService.Types
|
||||
|
@ -5,9 +5,9 @@ using LibHac.Fs.Fsa;
|
||||
using LibHac.FsSystem;
|
||||
using LibHac.Ncm;
|
||||
using LibHac.Tools.FsSystem.NcaUtils;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.HLE.HOS.SystemState;
|
||||
using Ryujinx.HLE.Utilities;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
@ -290,9 +290,7 @@ namespace Ryujinx.HLE.HOS.Services.Settings
|
||||
// NOTE: If miiAuthorId is null ResultCode.NullMiiAuthorIdBuffer is returned.
|
||||
// Doesn't occur in our case.
|
||||
|
||||
UInt128 miiAuthorId = Mii.Helper.GetDeviceId();
|
||||
|
||||
miiAuthorId.Write(context.ResponseData);
|
||||
context.ResponseData.Write(Mii.Helper.GetDeviceId());
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
@ -66,6 +66,8 @@ namespace Ryujinx.HLE.HOS.Services.Ssl.SslService
|
||||
EndSslOperation();
|
||||
}
|
||||
|
||||
// NOTE: We silence warnings about TLS 1.0 and 1.1 as games will likely use it.
|
||||
#pragma warning disable SYSLIB0039
|
||||
private static SslProtocols TranslateSslVersion(SslVersion version)
|
||||
{
|
||||
switch (version & SslVersion.VersionMask)
|
||||
@ -84,6 +86,7 @@ namespace Ryujinx.HLE.HOS.Services.Ssl.SslService
|
||||
throw new NotImplementedException(version.ToString());
|
||||
}
|
||||
}
|
||||
#pragma warning restore SYSLIB0039
|
||||
|
||||
public ResultCode Handshake(string hostName)
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
using Ryujinx.Cpu;
|
||||
using Ryujinx.HLE.Utilities;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using Ryujinx.Cpu;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
||||
@ -12,7 +12,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
||||
|
||||
public SteadyClockCore()
|
||||
{
|
||||
_clockSourceId = new UInt128(Guid.NewGuid().ToByteArray());
|
||||
_clockSourceId = UInt128Utils.CreateRandom();
|
||||
_isRtcResetDetected = false;
|
||||
_isInitialized = false;
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
using Ryujinx.HLE.Utilities;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
struct SteadyClockTimePoint
|
||||
{
|
||||
public long TimePoint;
|
||||
@ -36,7 +36,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
||||
return new SteadyClockTimePoint
|
||||
{
|
||||
TimePoint = 0,
|
||||
ClockSourceId = new UInt128(Guid.NewGuid().ToByteArray())
|
||||
ClockSourceId = UInt128Utils.CreateRandom()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
struct SystemClockContext
|
||||
{
|
||||
public long Offset;
|
||||
|
@ -3,7 +3,7 @@ using Ryujinx.HLE.Exceptions;
|
||||
using Ryujinx.HLE.HOS.Kernel.Memory;
|
||||
using Ryujinx.HLE.HOS.Services.Time.Clock;
|
||||
using Ryujinx.HLE.HOS.Services.Time.TimeZone;
|
||||
using Ryujinx.HLE.Utilities;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Time
|
||||
|
@ -1,6 +1,6 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.HLE.HOS.Services.Time.Clock;
|
||||
using Ryujinx.HLE.Utilities;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
||||
|
@ -1,9 +1,9 @@
|
||||
using Ryujinx.HLE.Utilities;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Time.Types
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
struct SteadyClockContext
|
||||
{
|
||||
public ulong InternalOffset;
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -1,75 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.HLE.Utilities
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct UInt128 : IEquatable<UInt128>
|
||||
{
|
||||
public readonly long Low;
|
||||
public readonly long High;
|
||||
|
||||
public bool IsNull => (Low | High) == 0;
|
||||
|
||||
public UInt128(long low, long high)
|
||||
{
|
||||
Low = low;
|
||||
High = high;
|
||||
}
|
||||
|
||||
public UInt128(byte[] bytes)
|
||||
{
|
||||
Low = BitConverter.ToInt64(bytes, 0);
|
||||
High = BitConverter.ToInt64(bytes, 8);
|
||||
}
|
||||
|
||||
public UInt128(string hex)
|
||||
{
|
||||
if (hex == null || hex.Length != 32 || !hex.All("0123456789abcdefABCDEF".Contains))
|
||||
{
|
||||
throw new ArgumentException("Invalid Hex value!", nameof(hex));
|
||||
}
|
||||
|
||||
Low = Convert.ToInt64(hex.Substring(16), 16);
|
||||
High = Convert.ToInt64(hex.Substring(0, 16), 16);
|
||||
}
|
||||
|
||||
public void Write(BinaryWriter binaryWriter)
|
||||
{
|
||||
binaryWriter.Write(Low);
|
||||
binaryWriter.Write(High);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return High.ToString("x16") + Low.ToString("x16");
|
||||
}
|
||||
|
||||
public static bool operator ==(UInt128 x, UInt128 y)
|
||||
{
|
||||
return x.Equals(y);
|
||||
}
|
||||
|
||||
public static bool operator !=(UInt128 x, UInt128 y)
|
||||
{
|
||||
return !x.Equals(y);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is UInt128 uint128 && Equals(uint128);
|
||||
}
|
||||
|
||||
public bool Equals(UInt128 cmpObj)
|
||||
{
|
||||
return Low == cmpObj.Low && High == cmpObj.High;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(Low, High);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<RuntimeIdentifiers>win10-x64;osx-x64;linux-x64</RuntimeIdentifiers>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Version>1.0.0-dirty</Version>
|
||||
<DefineConstants Condition=" '$(ExtraDefineConstants)' != '' ">$(DefineConstants);$(ExtraDefineConstants)</DefineConstants>
|
||||
<TieredPGO>true</TieredPGO>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@ -46,5 +47,6 @@
|
||||
<PropertyGroup Condition="'$(RuntimeIdentifier)' != ''">
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
<PublishTrimmed>true</PublishTrimmed>
|
||||
<TrimMode>partial</TrimMode>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -1,14 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Crc32.NET" Version="1.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ryujinx.HLE\Ryujinx.HLE.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
|
199
Ryujinx.Memory/Tracking/BitMap.cs
Normal file
199
Ryujinx.Memory/Tracking/BitMap.cs
Normal file
@ -0,0 +1,199 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Ryujinx.Memory.Tracking
|
||||
{
|
||||
/// <summary>
|
||||
/// A bitmap that can check or set large ranges of true/false values at once.
|
||||
/// </summary>
|
||||
struct BitMap
|
||||
{
|
||||
public const int IntSize = 64;
|
||||
|
||||
private const int IntShift = 6;
|
||||
private const int IntMask = IntSize - 1;
|
||||
|
||||
/// <summary>
|
||||
/// Masks representing the bitmap. Least significant bit first, 64-bits per mask.
|
||||
/// </summary>
|
||||
public readonly long[] Masks;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new bitmap.
|
||||
/// </summary>
|
||||
/// <param name="count">The number of bits to reserve</param>
|
||||
public BitMap(int count)
|
||||
{
|
||||
Masks = new long[(count + IntMask) / IntSize];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if any bit in the bitmap is set.
|
||||
/// </summary>
|
||||
/// <returns>True if any bits are set, false otherwise</returns>
|
||||
public bool AnySet()
|
||||
{
|
||||
for (int i = 0; i < Masks.Length; i++)
|
||||
{
|
||||
if (Masks[i] != 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if a bit in the bitmap is set.
|
||||
/// </summary>
|
||||
/// <param name="bit">The bit index to check</param>
|
||||
/// <returns>True if the bit is set, false otherwise</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool IsSet(int bit)
|
||||
{
|
||||
int wordIndex = bit >> IntShift;
|
||||
int wordBit = bit & IntMask;
|
||||
|
||||
long wordMask = 1L << wordBit;
|
||||
|
||||
return (Masks[wordIndex] & wordMask) != 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if any bit in a range of bits in the bitmap are set. (inclusive)
|
||||
/// </summary>
|
||||
/// <param name="start">The first bit index to check</param>
|
||||
/// <param name="end">The last bit index to check</param>
|
||||
/// <returns>True if a bit is set, false otherwise</returns>
|
||||
public bool IsSet(int start, int end)
|
||||
{
|
||||
if (start == end)
|
||||
{
|
||||
return IsSet(start);
|
||||
}
|
||||
|
||||
int startIndex = start >> IntShift;
|
||||
int startBit = start & IntMask;
|
||||
long startMask = -1L << startBit;
|
||||
|
||||
int endIndex = end >> IntShift;
|
||||
int endBit = end & IntMask;
|
||||
long endMask = (long)(ulong.MaxValue >> (IntMask - endBit));
|
||||
|
||||
if (startIndex == endIndex)
|
||||
{
|
||||
return (Masks[startIndex] & startMask & endMask) != 0;
|
||||
}
|
||||
|
||||
if ((Masks[startIndex] & startMask) != 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int i = startIndex + 1; i < endIndex; i++)
|
||||
{
|
||||
if (Masks[i] != 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((Masks[endIndex] & endMask) != 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a bit at a specific index to 1.
|
||||
/// </summary>
|
||||
/// <param name="bit">The bit index to set</param>
|
||||
/// <returns>True if the bit is set, false if it was already set</returns>
|
||||
public bool Set(int bit)
|
||||
{
|
||||
int wordIndex = bit >> IntShift;
|
||||
int wordBit = bit & IntMask;
|
||||
|
||||
long wordMask = 1L << wordBit;
|
||||
|
||||
if ((Masks[wordIndex] & wordMask) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Masks[wordIndex] |= wordMask;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a range of bits in the bitmap to 1.
|
||||
/// </summary>
|
||||
/// <param name="start">The first bit index to set</param>
|
||||
/// <param name="end">The last bit index to set</param>
|
||||
public void SetRange(int start, int end)
|
||||
{
|
||||
if (start == end)
|
||||
{
|
||||
Set(start);
|
||||
return;
|
||||
}
|
||||
|
||||
int startIndex = start >> IntShift;
|
||||
int startBit = start & IntMask;
|
||||
long startMask = -1L << startBit;
|
||||
|
||||
int endIndex = end >> IntShift;
|
||||
int endBit = end & IntMask;
|
||||
long endMask = (long)(ulong.MaxValue >> (IntMask - endBit));
|
||||
|
||||
if (startIndex == endIndex)
|
||||
{
|
||||
Masks[startIndex] |= startMask & endMask;
|
||||
}
|
||||
else
|
||||
{
|
||||
Masks[startIndex] |= startMask;
|
||||
|
||||
for (int i = startIndex + 1; i < endIndex; i++)
|
||||
{
|
||||
Masks[i] |= -1;
|
||||
}
|
||||
|
||||
Masks[endIndex] |= endMask;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear a bit at a specific index to 0.
|
||||
/// </summary>
|
||||
/// <param name="bit">The bit index to clear</param>
|
||||
/// <returns>True if the bit was set, false if it was not</returns>
|
||||
public bool Clear(int bit)
|
||||
{
|
||||
int wordIndex = bit >> IntShift;
|
||||
int wordBit = bit & IntMask;
|
||||
|
||||
long wordMask = 1L << wordBit;
|
||||
|
||||
bool wasSet = (Masks[wordIndex] & wordMask) != 0;
|
||||
|
||||
Masks[wordIndex] &= ~wordMask;
|
||||
|
||||
return wasSet;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear the bitmap entirely, setting all bits to 0.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
for (int i = 0; i < Masks.Length; i++)
|
||||
{
|
||||
Masks[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
161
Ryujinx.Memory/Tracking/ConcurrentBitmap.cs
Normal file
161
Ryujinx.Memory/Tracking/ConcurrentBitmap.cs
Normal file
@ -0,0 +1,161 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Ryujinx.Memory.Tracking
|
||||
{
|
||||
/// <summary>
|
||||
/// A bitmap that can be safely modified from multiple threads.
|
||||
/// </summary>
|
||||
internal class ConcurrentBitmap
|
||||
{
|
||||
public const int IntSize = 64;
|
||||
|
||||
public const int IntShift = 6;
|
||||
public const int IntMask = IntSize - 1;
|
||||
|
||||
/// <summary>
|
||||
/// Masks representing the bitmap. Least significant bit first, 64-bits per mask.
|
||||
/// </summary>
|
||||
public readonly long[] Masks;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new multithreaded bitmap.
|
||||
/// </summary>
|
||||
/// <param name="count">The number of bits to reserve</param>
|
||||
/// <param name="set">Whether the bits should be initially set or not</param>
|
||||
public ConcurrentBitmap(int count, bool set)
|
||||
{
|
||||
Masks = new long[(count + IntMask) / IntSize];
|
||||
|
||||
if (set)
|
||||
{
|
||||
Array.Fill(Masks, -1L);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if any bit in the bitmap is set.
|
||||
/// </summary>
|
||||
/// <returns>True if any bits are set, false otherwise</returns>
|
||||
public bool AnySet()
|
||||
{
|
||||
for (int i = 0; i < Masks.Length; i++)
|
||||
{
|
||||
if (Volatile.Read(ref Masks[i]) != 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if a bit in the bitmap is set.
|
||||
/// </summary>
|
||||
/// <param name="bit">The bit index to check</param>
|
||||
/// <returns>True if the bit is set, false otherwise</returns>
|
||||
public bool IsSet(int bit)
|
||||
{
|
||||
int wordIndex = bit >> IntShift;
|
||||
int wordBit = bit & IntMask;
|
||||
|
||||
long wordMask = 1L << wordBit;
|
||||
|
||||
return (Volatile.Read(ref Masks[wordIndex]) & wordMask) != 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if any bit in a range of bits in the bitmap are set. (inclusive)
|
||||
/// </summary>
|
||||
/// <param name="start">The first bit index to check</param>
|
||||
/// <param name="end">The last bit index to check</param>
|
||||
/// <returns>True if a bit is set, false otherwise</returns>
|
||||
public bool IsSet(int start, int end)
|
||||
{
|
||||
if (start == end)
|
||||
{
|
||||
return IsSet(start);
|
||||
}
|
||||
|
||||
int startIndex = start >> IntShift;
|
||||
int startBit = start & IntMask;
|
||||
long startMask = -1L << startBit;
|
||||
|
||||
int endIndex = end >> IntShift;
|
||||
int endBit = end & IntMask;
|
||||
long endMask = (long)(ulong.MaxValue >> (IntMask - endBit));
|
||||
|
||||
long startValue = Volatile.Read(ref Masks[startIndex]);
|
||||
|
||||
if (startIndex == endIndex)
|
||||
{
|
||||
return (startValue & startMask & endMask) != 0;
|
||||
}
|
||||
|
||||
if ((startValue & startMask) != 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int i = startIndex + 1; i < endIndex; i++)
|
||||
{
|
||||
if (Volatile.Read(ref Masks[i]) != 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
long endValue = Volatile.Read(ref Masks[endIndex]);
|
||||
|
||||
if ((endValue & endMask) != 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a bit at a specific index to either true or false.
|
||||
/// </summary>
|
||||
/// <param name="bit">The bit index to set</param>
|
||||
/// <param name="value">Whether the bit should be set or not</param>
|
||||
public void Set(int bit, bool value)
|
||||
{
|
||||
int wordIndex = bit >> IntShift;
|
||||
int wordBit = bit & IntMask;
|
||||
|
||||
long wordMask = 1L << wordBit;
|
||||
|
||||
long existing;
|
||||
long newValue;
|
||||
|
||||
do
|
||||
{
|
||||
existing = Volatile.Read(ref Masks[wordIndex]);
|
||||
|
||||
if (value)
|
||||
{
|
||||
newValue = existing | wordMask;
|
||||
}
|
||||
else
|
||||
{
|
||||
newValue = existing & ~wordMask;
|
||||
}
|
||||
}
|
||||
while (Interlocked.CompareExchange(ref Masks[wordIndex], newValue, existing) != existing);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear the bitmap entirely, setting all bits to 0.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
for (int i = 0; i < Masks.Length; i++)
|
||||
{
|
||||
Volatile.Write(ref Masks[i], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -176,6 +176,26 @@ namespace Ryujinx.Memory.Tracking
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Obtains a memory tracking handle for the given virtual region. This should be disposed when finished with.
|
||||
/// </summary>
|
||||
/// <param name="address">CPU virtual address of the region</param>
|
||||
/// <param name="size">Size of the region</param>
|
||||
/// <param name="bitmap">The bitmap owning the dirty flag for this handle</param>
|
||||
/// <param name="bit">The bit of this handle within the dirty flag</param>
|
||||
/// <returns>The memory tracking handle</returns>
|
||||
internal RegionHandle BeginTrackingBitmap(ulong address, ulong size, ConcurrentBitmap bitmap, int bit)
|
||||
{
|
||||
(address, size) = PageAlign(address, size);
|
||||
|
||||
lock (TrackingLock)
|
||||
{
|
||||
RegionHandle handle = new RegionHandle(this, address, size, bitmap, bit, _memoryManager.IsRangeMapped(address, size));
|
||||
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Signal that a virtual memory event happened at the given location (one byte).
|
||||
/// </summary>
|
||||
|
@ -1,11 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace Ryujinx.Memory.Tracking
|
||||
{
|
||||
/// <summary>
|
||||
/// A region handle that tracks a large region using many smaller handles, to provide
|
||||
/// granular tracking that can be used to track partial updates.
|
||||
/// granular tracking that can be used to track partial updates. Backed by a bitmap
|
||||
/// to improve performance when scanning large regions.
|
||||
/// </summary>
|
||||
public class MultiRegionHandle : IMultiRegionHandle
|
||||
{
|
||||
@ -17,6 +21,12 @@ namespace Ryujinx.Memory.Tracking
|
||||
private readonly ulong Granularity;
|
||||
private readonly ulong Size;
|
||||
|
||||
private ConcurrentBitmap _dirtyBitmap;
|
||||
|
||||
private int _sequenceNumber;
|
||||
private BitMap _sequenceNumberBitmap;
|
||||
private int _uncheckedHandles;
|
||||
|
||||
public bool Dirty { get; private set; } = true;
|
||||
|
||||
internal MultiRegionHandle(MemoryTracking tracking, ulong address, ulong size, IEnumerable<IRegionHandle> handles, ulong granularity)
|
||||
@ -24,6 +34,9 @@ namespace Ryujinx.Memory.Tracking
|
||||
_handles = new RegionHandle[size / granularity];
|
||||
Granularity = granularity;
|
||||
|
||||
_dirtyBitmap = new ConcurrentBitmap(_handles.Length, true);
|
||||
_sequenceNumberBitmap = new BitMap(_handles.Length);
|
||||
|
||||
int i = 0;
|
||||
|
||||
if (handles != null)
|
||||
@ -40,37 +53,43 @@ namespace Ryujinx.Memory.Tracking
|
||||
// Fill any gap left before this handle.
|
||||
while (i < startIndex)
|
||||
{
|
||||
RegionHandle fillHandle = tracking.BeginTracking(address + (ulong)i * granularity, granularity);
|
||||
RegionHandle fillHandle = tracking.BeginTrackingBitmap(address + (ulong)i * granularity, granularity, _dirtyBitmap, i);
|
||||
fillHandle.Parent = this;
|
||||
_handles[i++] = fillHandle;
|
||||
}
|
||||
|
||||
if (handle.Size == granularity)
|
||||
lock (tracking.TrackingLock)
|
||||
{
|
||||
handle.Parent = this;
|
||||
_handles[i++] = handle;
|
||||
}
|
||||
else
|
||||
{
|
||||
int endIndex = (int)((handle.EndAddress - address) / granularity);
|
||||
|
||||
while (i < endIndex)
|
||||
if (handle is RegionHandle bitHandle && handle.Size == granularity)
|
||||
{
|
||||
RegionHandle splitHandle = tracking.BeginTracking(address + (ulong)i * granularity, granularity);
|
||||
splitHandle.Parent = this;
|
||||
handle.Parent = this;
|
||||
|
||||
splitHandle.Reprotect(handle.Dirty);
|
||||
bitHandle.ReplaceBitmap(_dirtyBitmap, i);
|
||||
|
||||
RegionSignal signal = handle.PreAction;
|
||||
if (signal != null)
|
||||
_handles[i++] = bitHandle;
|
||||
}
|
||||
else
|
||||
{
|
||||
int endIndex = (int)((handle.EndAddress - address) / granularity);
|
||||
|
||||
while (i < endIndex)
|
||||
{
|
||||
splitHandle.RegisterAction(signal);
|
||||
RegionHandle splitHandle = tracking.BeginTrackingBitmap(address + (ulong)i * granularity, granularity, _dirtyBitmap, i);
|
||||
splitHandle.Parent = this;
|
||||
|
||||
splitHandle.Reprotect(handle.Dirty);
|
||||
|
||||
RegionSignal signal = handle.PreAction;
|
||||
if (signal != null)
|
||||
{
|
||||
splitHandle.RegisterAction(signal);
|
||||
}
|
||||
|
||||
_handles[i++] = splitHandle;
|
||||
}
|
||||
|
||||
_handles[i++] = splitHandle;
|
||||
handle.Dispose();
|
||||
}
|
||||
|
||||
handle.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -78,15 +97,27 @@ namespace Ryujinx.Memory.Tracking
|
||||
// Fill any remaining space with new handles.
|
||||
while (i < _handles.Length)
|
||||
{
|
||||
RegionHandle handle = tracking.BeginTracking(address + (ulong)i * granularity, granularity);
|
||||
RegionHandle handle = tracking.BeginTrackingBitmap(address + (ulong)i * granularity, granularity, _dirtyBitmap, i);
|
||||
handle.Parent = this;
|
||||
_handles[i++] = handle;
|
||||
}
|
||||
|
||||
_uncheckedHandles = _handles.Length;
|
||||
|
||||
Address = address;
|
||||
Size = size;
|
||||
}
|
||||
|
||||
public void SignalWrite()
|
||||
{
|
||||
Dirty = true;
|
||||
}
|
||||
|
||||
public IEnumerable<RegionHandle> GetHandles()
|
||||
{
|
||||
return _handles;
|
||||
}
|
||||
|
||||
public void ForceDirty(ulong address, ulong size)
|
||||
{
|
||||
Dirty = true;
|
||||
@ -96,21 +127,15 @@ namespace Ryujinx.Memory.Tracking
|
||||
|
||||
for (int i = startHandle; i <= lastHandle; i++)
|
||||
{
|
||||
_handles[i].SequenceNumber--;
|
||||
if (_sequenceNumberBitmap.Clear(i))
|
||||
{
|
||||
_uncheckedHandles++;
|
||||
}
|
||||
|
||||
_handles[i].ForceDirty();
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<RegionHandle> GetHandles()
|
||||
{
|
||||
return _handles;
|
||||
}
|
||||
|
||||
public void SignalWrite()
|
||||
{
|
||||
Dirty = true;
|
||||
}
|
||||
|
||||
public void QueryModified(Action<ulong, ulong> modifiedAction)
|
||||
{
|
||||
if (!Dirty)
|
||||
@ -123,33 +148,95 @@ namespace Ryujinx.Memory.Tracking
|
||||
QueryModified(Address, Size, modifiedAction);
|
||||
}
|
||||
|
||||
public void QueryModified(ulong address, ulong size, Action<ulong, ulong> modifiedAction)
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void ParseDirtyBits(long dirtyBits, ref int baseBit, ref int prevHandle, ref ulong rgStart, ref ulong rgSize, Action<ulong, ulong> modifiedAction)
|
||||
{
|
||||
int startHandle = (int)((address - Address) / Granularity);
|
||||
int lastHandle = (int)((address + (size - 1) - Address) / Granularity);
|
||||
|
||||
ulong rgStart = _handles[startHandle].Address;
|
||||
ulong rgSize = 0;
|
||||
|
||||
for (int i = startHandle; i <= lastHandle; i++)
|
||||
while (dirtyBits != 0)
|
||||
{
|
||||
RegionHandle handle = _handles[i];
|
||||
int bit = BitOperations.TrailingZeroCount(dirtyBits);
|
||||
|
||||
dirtyBits &= ~(1L << bit);
|
||||
|
||||
int handleIndex = baseBit + bit;
|
||||
|
||||
RegionHandle handle = _handles[handleIndex];
|
||||
|
||||
if (handleIndex != prevHandle + 1)
|
||||
{
|
||||
// Submit handles scanned until the gap as dirty
|
||||
if (rgSize != 0)
|
||||
{
|
||||
modifiedAction(rgStart, rgSize);
|
||||
rgSize = 0;
|
||||
}
|
||||
rgStart = handle.Address;
|
||||
}
|
||||
|
||||
if (handle.Dirty)
|
||||
{
|
||||
rgSize += handle.Size;
|
||||
handle.Reprotect();
|
||||
}
|
||||
else
|
||||
|
||||
prevHandle = handleIndex;
|
||||
}
|
||||
|
||||
baseBit += ConcurrentBitmap.IntSize;
|
||||
}
|
||||
|
||||
public void QueryModified(ulong address, ulong size, Action<ulong, ulong> modifiedAction)
|
||||
{
|
||||
int startHandle = (int)((address - Address) / Granularity);
|
||||
int lastHandle = (int)((address + (size - 1) - Address) / Granularity);
|
||||
|
||||
ulong rgStart = _handles[startHandle].Address;
|
||||
|
||||
if (startHandle == lastHandle)
|
||||
{
|
||||
RegionHandle handle = _handles[startHandle];
|
||||
|
||||
if (handle.Dirty)
|
||||
{
|
||||
// Submit the region scanned so far as dirty
|
||||
if (rgSize != 0)
|
||||
{
|
||||
modifiedAction(rgStart, rgSize);
|
||||
rgSize = 0;
|
||||
}
|
||||
rgStart = handle.EndAddress;
|
||||
handle.Reprotect();
|
||||
modifiedAction(rgStart, handle.Size);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ulong rgSize = 0;
|
||||
|
||||
long[] masks = _dirtyBitmap.Masks;
|
||||
|
||||
int startIndex = startHandle >> ConcurrentBitmap.IntShift;
|
||||
int startBit = startHandle & ConcurrentBitmap.IntMask;
|
||||
long startMask = -1L << startBit;
|
||||
|
||||
int endIndex = lastHandle >> ConcurrentBitmap.IntShift;
|
||||
int endBit = lastHandle & ConcurrentBitmap.IntMask;
|
||||
long endMask = (long)(ulong.MaxValue >> (ConcurrentBitmap.IntMask - endBit));
|
||||
|
||||
long startValue = Volatile.Read(ref masks[startIndex]);
|
||||
|
||||
int baseBit = startIndex << ConcurrentBitmap.IntShift;
|
||||
int prevHandle = startHandle - 1;
|
||||
|
||||
if (startIndex == endIndex)
|
||||
{
|
||||
ParseDirtyBits(startValue & startMask & endMask, ref baseBit, ref prevHandle, ref rgStart, ref rgSize, modifiedAction);
|
||||
}
|
||||
else
|
||||
{
|
||||
ParseDirtyBits(startValue & startMask, ref baseBit, ref prevHandle, ref rgStart, ref rgSize, modifiedAction);
|
||||
|
||||
for (int i = startIndex + 1; i < endIndex; i++)
|
||||
{
|
||||
ParseDirtyBits(Volatile.Read(ref masks[i]), ref baseBit, ref prevHandle, ref rgStart, ref rgSize, modifiedAction);
|
||||
}
|
||||
|
||||
long endValue = Volatile.Read(ref masks[endIndex]);
|
||||
|
||||
ParseDirtyBits(endValue & endMask, ref baseBit, ref prevHandle, ref rgStart, ref rgSize, modifiedAction);
|
||||
}
|
||||
|
||||
if (rgSize != 0)
|
||||
@ -158,35 +245,120 @@ namespace Ryujinx.Memory.Tracking
|
||||
}
|
||||
}
|
||||
|
||||
public void QueryModified(ulong address, ulong size, Action<ulong, ulong> modifiedAction, int sequenceNumber)
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void ParseDirtyBits(long dirtyBits, long mask, int index, long[] seqMasks, ref int baseBit, ref int prevHandle, ref ulong rgStart, ref ulong rgSize, Action<ulong, ulong> modifiedAction)
|
||||
{
|
||||
int startHandle = (int)((address - Address) / Granularity);
|
||||
int lastHandle = (int)((address + (size - 1) - Address) / Granularity);
|
||||
long seqMask = mask & ~seqMasks[index];
|
||||
dirtyBits &= seqMask;
|
||||
|
||||
ulong rgStart = _handles[startHandle].Address;
|
||||
ulong rgSize = 0;
|
||||
|
||||
for (int i = startHandle; i <= lastHandle; i++)
|
||||
while (dirtyBits != 0)
|
||||
{
|
||||
RegionHandle handle = _handles[i];
|
||||
int bit = BitOperations.TrailingZeroCount(dirtyBits);
|
||||
|
||||
if (sequenceNumber != handle.SequenceNumber && handle.DirtyOrVolatile())
|
||||
dirtyBits &= ~(1L << bit);
|
||||
|
||||
int handleIndex = baseBit + bit;
|
||||
|
||||
RegionHandle handle = _handles[handleIndex];
|
||||
|
||||
if (handleIndex != prevHandle + 1)
|
||||
{
|
||||
rgSize += handle.Size;
|
||||
handle.Reprotect();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Submit the region scanned so far as dirty
|
||||
// Submit handles scanned until the gap as dirty
|
||||
if (rgSize != 0)
|
||||
{
|
||||
modifiedAction(rgStart, rgSize);
|
||||
rgSize = 0;
|
||||
}
|
||||
rgStart = handle.EndAddress;
|
||||
rgStart = handle.Address;
|
||||
}
|
||||
|
||||
handle.SequenceNumber = sequenceNumber;
|
||||
rgSize += handle.Size;
|
||||
handle.Reprotect();
|
||||
|
||||
prevHandle = handleIndex;
|
||||
}
|
||||
|
||||
seqMasks[index] |= mask;
|
||||
_uncheckedHandles -= BitOperations.PopCount((ulong)seqMask);
|
||||
|
||||
baseBit += ConcurrentBitmap.IntSize;
|
||||
}
|
||||
|
||||
public void QueryModified(ulong address, ulong size, Action<ulong, ulong> modifiedAction, int sequenceNumber)
|
||||
{
|
||||
int startHandle = (int)((address - Address) / Granularity);
|
||||
int lastHandle = (int)((address + (size - 1) - Address) / Granularity);
|
||||
|
||||
ulong rgStart = Address + (ulong)startHandle * Granularity;
|
||||
|
||||
if (sequenceNumber != _sequenceNumber)
|
||||
{
|
||||
if (_uncheckedHandles != _handles.Length)
|
||||
{
|
||||
_sequenceNumberBitmap.Clear();
|
||||
_uncheckedHandles = _handles.Length;
|
||||
}
|
||||
|
||||
_sequenceNumber = sequenceNumber;
|
||||
}
|
||||
|
||||
if (startHandle == lastHandle)
|
||||
{
|
||||
var handle = _handles[startHandle];
|
||||
if (_sequenceNumberBitmap.Set(startHandle))
|
||||
{
|
||||
_uncheckedHandles--;
|
||||
|
||||
if (handle.DirtyOrVolatile())
|
||||
{
|
||||
handle.Reprotect();
|
||||
|
||||
modifiedAction(rgStart, handle.Size);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (_uncheckedHandles == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ulong rgSize = 0;
|
||||
|
||||
long[] seqMasks = _sequenceNumberBitmap.Masks;
|
||||
long[] masks = _dirtyBitmap.Masks;
|
||||
|
||||
int startIndex = startHandle >> ConcurrentBitmap.IntShift;
|
||||
int startBit = startHandle & ConcurrentBitmap.IntMask;
|
||||
long startMask = -1L << startBit;
|
||||
|
||||
int endIndex = lastHandle >> ConcurrentBitmap.IntShift;
|
||||
int endBit = lastHandle & ConcurrentBitmap.IntMask;
|
||||
long endMask = (long)(ulong.MaxValue >> (ConcurrentBitmap.IntMask - endBit));
|
||||
|
||||
long startValue = Volatile.Read(ref masks[startIndex]);
|
||||
|
||||
int baseBit = startIndex << ConcurrentBitmap.IntShift;
|
||||
int prevHandle = startHandle - 1;
|
||||
|
||||
if (startIndex == endIndex)
|
||||
{
|
||||
ParseDirtyBits(startValue, startMask & endMask, startIndex, seqMasks, ref baseBit, ref prevHandle, ref rgStart, ref rgSize, modifiedAction);
|
||||
}
|
||||
else
|
||||
{
|
||||
ParseDirtyBits(startValue, startMask, startIndex, seqMasks, ref baseBit, ref prevHandle, ref rgStart, ref rgSize, modifiedAction);
|
||||
|
||||
for (int i = startIndex + 1; i < endIndex; i++)
|
||||
{
|
||||
ParseDirtyBits(Volatile.Read(ref masks[i]), -1L, i, seqMasks, ref baseBit, ref prevHandle, ref rgStart, ref rgSize, modifiedAction);
|
||||
}
|
||||
|
||||
long endValue = Volatile.Read(ref masks[endIndex]);
|
||||
|
||||
ParseDirtyBits(endValue, endMask, endIndex, seqMasks, ref baseBit, ref prevHandle, ref rgStart, ref rgSize, modifiedAction);
|
||||
}
|
||||
|
||||
if (rgSize != 0)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user