Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
d7c6474729 | |||
1ecc8fbc3b | |||
888402ecaf | |||
971d24aef0 | |||
c41fddd25e |
@ -20,7 +20,7 @@
|
|||||||
<PackageVersion Include="LibHac" Version="0.19.0" />
|
<PackageVersion Include="LibHac" Version="0.19.0" />
|
||||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
||||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" />
|
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" />
|
||||||
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="7.5.2" />
|
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="7.6.0" />
|
||||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||||
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.0" />
|
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.0" />
|
||||||
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
|
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
|
||||||
|
@ -237,7 +237,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
long originalPosition = _stream.Position;
|
long originalPosition = _stream.Position;
|
||||||
|
|
||||||
_stream.Seek(0, SeekOrigin.Begin);
|
_stream.Seek(0, SeekOrigin.Begin);
|
||||||
_stream.Read(code, 0, code.Length);
|
_stream.ReadExactly(code, 0, code.Length);
|
||||||
_stream.Seek(originalPosition, SeekOrigin.Begin);
|
_stream.Seek(originalPosition, SeekOrigin.Begin);
|
||||||
|
|
||||||
RelocInfo relocInfo;
|
RelocInfo relocInfo;
|
||||||
|
@ -1444,7 +1444,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
Span<byte> buffer = new byte[jump.JumpPosition - _stream.Position];
|
Span<byte> buffer = new byte[jump.JumpPosition - _stream.Position];
|
||||||
|
|
||||||
_stream.Read(buffer);
|
_stream.ReadExactly(buffer);
|
||||||
_stream.Seek(ReservedBytesForJump, SeekOrigin.Current);
|
_stream.Seek(ReservedBytesForJump, SeekOrigin.Current);
|
||||||
|
|
||||||
codeStream.Write(buffer);
|
codeStream.Write(buffer);
|
||||||
|
140
src/Ryujinx.Common/Memory/MemoryOwner.cs
Normal file
140
src/Ryujinx.Common/Memory/MemoryOwner.cs
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System;
|
||||||
|
using System.Buffers;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Ryujinx.Common.Memory
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An <see cref="IMemoryOwner{T}"/> implementation with an embedded length and fast <see cref="Span{T}"/>
|
||||||
|
/// accessor, with memory allocated from <seealso cref="ArrayPool{T}.Shared"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The type of item to store.</typeparam>
|
||||||
|
public sealed class MemoryOwner<T> : IMemoryOwner<T>
|
||||||
|
{
|
||||||
|
private readonly int _length;
|
||||||
|
private T[]? _array;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MemoryOwner{T}"/> class with the specified parameters.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="length">The length of the new memory buffer to use</param>
|
||||||
|
private MemoryOwner(int length)
|
||||||
|
{
|
||||||
|
_length = length;
|
||||||
|
_array = ArrayPool<T>.Shared.Rent(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="MemoryOwner{T}"/> instance with the specified length.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="length">The length of the new memory buffer to use</param>
|
||||||
|
/// <returns>A <see cref="MemoryOwner{T}"/> instance of the requested length</returns>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="length"/> is not valid</exception>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static MemoryOwner<T> Rent(int length) => new(length);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="MemoryOwner{T}"/> instance with the specified length and the content cleared.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="length">The length of the new memory buffer to use</param>
|
||||||
|
/// <returns>A <see cref="MemoryOwner{T}"/> instance of the requested length and the content cleared</returns>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="length"/> is not valid</exception>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static MemoryOwner<T> RentCleared(int length)
|
||||||
|
{
|
||||||
|
MemoryOwner<T> result = new(length);
|
||||||
|
|
||||||
|
result._array.AsSpan(0, length).Clear();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="MemoryOwner{T}"/> instance with the content copied from the specified buffer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buffer">The buffer to copy</param>
|
||||||
|
/// <returns>A <see cref="MemoryOwner{T}"/> instance with the same length and content as <paramref name="buffer"/></returns>
|
||||||
|
public static MemoryOwner<T> RentCopy(ReadOnlySpan<T> buffer)
|
||||||
|
{
|
||||||
|
MemoryOwner<T> result = new(buffer.Length);
|
||||||
|
|
||||||
|
buffer.CopyTo(result._array);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the number of items in the current instance.
|
||||||
|
/// </summary>
|
||||||
|
public int Length
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get => _length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public Memory<T> Memory
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
T[]? array = _array;
|
||||||
|
|
||||||
|
if (array is null)
|
||||||
|
{
|
||||||
|
ThrowObjectDisposedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new(array, 0, _length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a <see cref="Span{T}"/> wrapping the memory belonging to the current instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Uses a trick made possible by the .NET 6+ runtime array layout.
|
||||||
|
/// </remarks>
|
||||||
|
public Span<T> Span
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
T[]? array = _array;
|
||||||
|
|
||||||
|
if (array is null)
|
||||||
|
{
|
||||||
|
ThrowObjectDisposedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
ref T firstElementRef = ref MemoryMarshal.GetArrayDataReference(array);
|
||||||
|
|
||||||
|
return MemoryMarshal.CreateSpan(ref firstElementRef, _length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
T[]? array = Interlocked.Exchange(ref _array, null);
|
||||||
|
|
||||||
|
if (array is not null)
|
||||||
|
{
|
||||||
|
ArrayPool<T>.Shared.Return(array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Throws an <see cref="ObjectDisposedException"/> when <see cref="_array"/> is <see langword="null"/>.
|
||||||
|
/// </summary>
|
||||||
|
[DoesNotReturn]
|
||||||
|
private static void ThrowObjectDisposedException()
|
||||||
|
{
|
||||||
|
throw new ObjectDisposedException(nameof(MemoryOwner<T>), "The buffer has already been disposed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
114
src/Ryujinx.Common/Memory/SpanOwner.cs
Normal file
114
src/Ryujinx.Common/Memory/SpanOwner.cs
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
using System;
|
||||||
|
using System.Buffers;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Ryujinx.Common.Memory
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A stack-only type that rents a buffer of a specified length from <seealso cref="ArrayPool{T}.Shared"/>.
|
||||||
|
/// It does not implement <see cref="IDisposable"/> to avoid being boxed, but should still be disposed. This
|
||||||
|
/// is easy since C# 8, which allows use of C# `using` constructs on any type that has a public Dispose() method.
|
||||||
|
/// To keep this type simple, fast, and read-only, it does not check or guard against multiple disposals.
|
||||||
|
/// For all these reasons, all usage should be with a `using` block or statement.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The type of item to store.</typeparam>
|
||||||
|
public readonly ref struct SpanOwner<T>
|
||||||
|
{
|
||||||
|
private readonly int _length;
|
||||||
|
private readonly T[] _array;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="SpanOwner{T}"/> struct with the specified parameters.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="length">The length of the new memory buffer to use</param>
|
||||||
|
private SpanOwner(int length)
|
||||||
|
{
|
||||||
|
_length = length;
|
||||||
|
_array = ArrayPool<T>.Shared.Rent(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets an empty <see cref="SpanOwner{T}"/> instance.
|
||||||
|
/// </summary>
|
||||||
|
public static SpanOwner<T> Empty
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get => new(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="SpanOwner{T}"/> instance with the specified length.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="length">The length of the new memory buffer to use</param>
|
||||||
|
/// <returns>A <see cref="SpanOwner{T}"/> instance of the requested length</returns>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="length"/> is not valid</exception>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static SpanOwner<T> Rent(int length) => new(length);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="SpanOwner{T}"/> instance with the length and the content cleared.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="length">The length of the new memory buffer to use</param>
|
||||||
|
/// <returns>A <see cref="SpanOwner{T}"/> instance of the requested length and the content cleared</returns>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="length"/> is not valid</exception>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static SpanOwner<T> RentCleared(int length)
|
||||||
|
{
|
||||||
|
SpanOwner<T> result = new(length);
|
||||||
|
|
||||||
|
result._array.AsSpan(0, length).Clear();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="SpanOwner{T}"/> instance with the content copied from the specified buffer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buffer">The buffer to copy</param>
|
||||||
|
/// <returns>A <see cref="SpanOwner{T}"/> instance with the same length and content as <paramref name="buffer"/></returns>
|
||||||
|
public static SpanOwner<T> RentCopy(ReadOnlySpan<T> buffer)
|
||||||
|
{
|
||||||
|
SpanOwner<T> result = new(buffer.Length);
|
||||||
|
|
||||||
|
buffer.CopyTo(result._array);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the number of items in the current instance
|
||||||
|
/// </summary>
|
||||||
|
public int Length
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get => _length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a <see cref="Span{T}"/> wrapping the memory belonging to the current instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Uses a trick made possible by the .NET 6+ runtime array layout.
|
||||||
|
/// </remarks>
|
||||||
|
public Span<T> Span
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
ref T firstElementRef = ref MemoryMarshal.GetArrayDataReference(_array);
|
||||||
|
|
||||||
|
return MemoryMarshal.CreateSpan(ref firstElementRef, _length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implements the duck-typed <see cref="IDisposable.Dispose"/> method.
|
||||||
|
/// </summary>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
ArrayPool<T>.Shared.Return(_array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -195,7 +195,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
switch (algorithm)
|
switch (algorithm)
|
||||||
{
|
{
|
||||||
case CompressionAlgorithm.None:
|
case CompressionAlgorithm.None:
|
||||||
stream.Read(data);
|
stream.ReadExactly(data);
|
||||||
break;
|
break;
|
||||||
case CompressionAlgorithm.Deflate:
|
case CompressionAlgorithm.Deflate:
|
||||||
stream = new DeflateStream(stream, CompressionMode.Decompress, true);
|
stream = new DeflateStream(stream, CompressionMode.Decompress, true);
|
||||||
|
@ -220,7 +220,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
}
|
}
|
||||||
|
|
||||||
dataFileStream.Seek((long)entry.Offset, SeekOrigin.Begin);
|
dataFileStream.Seek((long)entry.Offset, SeekOrigin.Begin);
|
||||||
dataFileStream.Read(cb1Data);
|
dataFileStream.ReadExactly(cb1Data);
|
||||||
BinarySerializer.ReadCompressed(dataFileStream, guestCode);
|
BinarySerializer.ReadCompressed(dataFileStream, guestCode);
|
||||||
|
|
||||||
_cache[index] = (guestCode, cb1Data);
|
_cache[index] = (guestCode, cb1Data);
|
||||||
@ -279,7 +279,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
dataFileStream.Seek((long)entry.Offset, SeekOrigin.Begin);
|
dataFileStream.Seek((long)entry.Offset, SeekOrigin.Begin);
|
||||||
byte[] cachedCode = new byte[entry.CodeSize];
|
byte[] cachedCode = new byte[entry.CodeSize];
|
||||||
byte[] cachedCb1Data = new byte[entry.Cb1DataSize];
|
byte[] cachedCb1Data = new byte[entry.Cb1DataSize];
|
||||||
dataFileStream.Read(cachedCb1Data);
|
dataFileStream.ReadExactly(cachedCb1Data);
|
||||||
BinarySerializer.ReadCompressed(dataFileStream, cachedCode);
|
BinarySerializer.ReadCompressed(dataFileStream, cachedCode);
|
||||||
|
|
||||||
if (data.SequenceEqual(cachedCode) && cb1Data.SequenceEqual(cachedCb1Data))
|
if (data.SequenceEqual(cachedCode) && cb1Data.SequenceEqual(cachedCb1Data))
|
||||||
|
@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
private const ushort FileFormatVersionMajor = 1;
|
private const ushort FileFormatVersionMajor = 1;
|
||||||
private const ushort FileFormatVersionMinor = 2;
|
private const ushort FileFormatVersionMinor = 2;
|
||||||
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
|
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
|
||||||
private const uint CodeGenVersion = 6870;
|
private const uint CodeGenVersion = 6852;
|
||||||
|
|
||||||
private const string SharedTocFileName = "shared.toc";
|
private const string SharedTocFileName = "shared.toc";
|
||||||
private const string SharedDataFileName = "shared.data";
|
private const string SharedDataFileName = "shared.data";
|
||||||
|
@ -38,6 +38,12 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||||||
// If we can't do bindless elimination, remove the texture operation.
|
// If we can't do bindless elimination, remove the texture operation.
|
||||||
// Set any destination variables to zero.
|
// Set any destination variables to zero.
|
||||||
|
|
||||||
|
string typeName = texOp.Inst.IsImage()
|
||||||
|
? texOp.Type.ToGlslImageType(texOp.Format.GetComponentType())
|
||||||
|
: texOp.Type.ToGlslTextureType();
|
||||||
|
|
||||||
|
gpuAccessor.Log($"Failed to find handle source for bindless access of type \"{typeName}\".");
|
||||||
|
|
||||||
for (int destIndex = 0; destIndex < texOp.DestsCount; destIndex++)
|
for (int destIndex = 0; destIndex < texOp.DestsCount; destIndex++)
|
||||||
{
|
{
|
||||||
block.Operations.AddBefore(node, new Operation(Instruction.Copy, texOp.GetDest(destIndex), OperandHelper.Const(0)));
|
block.Operations.AddBefore(node, new Operation(Instruction.Copy, texOp.GetDest(destIndex), OperandHelper.Const(0)));
|
||||||
@ -62,17 +68,22 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Operand nvHandle = texOp.GetSource(0);
|
Operand bindlessHandle = texOp.GetSource(0);
|
||||||
|
|
||||||
if (nvHandle.AsgOp is not Operation handleOp ||
|
if (bindlessHandle.AsgOp is PhiNode phi)
|
||||||
handleOp.Inst != Instruction.Load ||
|
|
||||||
(handleOp.StorageKind != StorageKind.Input && handleOp.StorageKind != StorageKind.StorageBuffer))
|
|
||||||
{
|
{
|
||||||
// Right now, we only allow bindless access when the handle comes from a shader input or storage buffer.
|
for (int srcIndex = 0; srcIndex < phi.SourcesCount; srcIndex++)
|
||||||
// This is an artificial limitation to prevent it from being used in cases where it
|
{
|
||||||
// would have a large performance impact of loading all textures in the pool.
|
Operand phiSource = phi.GetSource(srcIndex);
|
||||||
// It might be removed in the future, if we can mitigate the performance impact.
|
|
||||||
|
|
||||||
|
if (phiSource.AsgOp is not PhiNode && !IsBindlessAccessAllowed(phiSource))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!IsBindlessAccessAllowed(bindlessHandle))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,8 +91,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||||||
Operand samplerHandle = OperandHelper.Local();
|
Operand samplerHandle = OperandHelper.Local();
|
||||||
Operand textureIndex = OperandHelper.Local();
|
Operand textureIndex = OperandHelper.Local();
|
||||||
|
|
||||||
block.Operations.AddBefore(node, new Operation(Instruction.BitwiseAnd, textureHandle, nvHandle, OperandHelper.Const(0xfffff)));
|
block.Operations.AddBefore(node, new Operation(Instruction.BitwiseAnd, textureHandle, bindlessHandle, OperandHelper.Const(0xfffff)));
|
||||||
block.Operations.AddBefore(node, new Operation(Instruction.ShiftRightU32, samplerHandle, nvHandle, OperandHelper.Const(20)));
|
block.Operations.AddBefore(node, new Operation(Instruction.ShiftRightU32, samplerHandle, bindlessHandle, OperandHelper.Const(20)));
|
||||||
|
|
||||||
int texturePoolLength = Math.Max(BindlessToArray.MinimumArrayLength, gpuAccessor.QueryTextureArrayLengthFromPool());
|
int texturePoolLength = Math.Max(BindlessToArray.MinimumArrayLength, gpuAccessor.QueryTextureArrayLengthFromPool());
|
||||||
|
|
||||||
@ -130,6 +141,30 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool IsBindlessAccessAllowed(Operand nvHandle)
|
||||||
|
{
|
||||||
|
if (nvHandle.Type == OperandType.ConstantBuffer)
|
||||||
|
{
|
||||||
|
// Bindless access with handles from constant buffer is allowed.
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nvHandle.AsgOp is not Operation handleOp ||
|
||||||
|
handleOp.Inst != Instruction.Load ||
|
||||||
|
(handleOp.StorageKind != StorageKind.Input && handleOp.StorageKind != StorageKind.StorageBuffer))
|
||||||
|
{
|
||||||
|
// Right now, we only allow bindless access when the handle comes from a shader input or storage buffer.
|
||||||
|
// This is an artificial limitation to prevent it from being used in cases where it
|
||||||
|
// would have a large performance impact of loading all textures in the pool.
|
||||||
|
// It might be removed in the future, if we can mitigate the performance impact.
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private static bool TryConvertBindless(BasicBlock block, ResourceManager resourceManager, IGpuAccessor gpuAccessor, TextureOperation texOp)
|
private static bool TryConvertBindless(BasicBlock block, ResourceManager resourceManager, IGpuAccessor gpuAccessor, TextureOperation texOp)
|
||||||
{
|
{
|
||||||
if (texOp.Inst == Instruction.TextureSample || texOp.Inst.IsTextureQuery())
|
if (texOp.Inst == Instruction.TextureSample || texOp.Inst.IsTextureQuery())
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using Ryujinx.Common.Memory;
|
||||||
using Silk.NET.Vulkan;
|
using Silk.NET.Vulkan;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
@ -165,14 +166,15 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
/// <returns>True if all fences were signaled before the timeout expired, false otherwise</returns>
|
/// <returns>True if all fences were signaled before the timeout expired, false otherwise</returns>
|
||||||
private bool WaitForFencesImpl(Vk api, Device device, int offset, int size, bool hasTimeout, ulong timeout)
|
private bool WaitForFencesImpl(Vk api, Device device, int offset, int size, bool hasTimeout, ulong timeout)
|
||||||
{
|
{
|
||||||
Span<FenceHolder> fenceHolders = new FenceHolder[CommandBufferPool.MaxCommandBuffers];
|
using SpanOwner<FenceHolder> fenceHoldersOwner = SpanOwner<FenceHolder>.Rent(CommandBufferPool.MaxCommandBuffers);
|
||||||
|
Span<FenceHolder> fenceHolders = fenceHoldersOwner.Span;
|
||||||
|
|
||||||
int count = size != 0 ? GetOverlappingFences(fenceHolders, offset, size) : GetFences(fenceHolders);
|
int count = size != 0 ? GetOverlappingFences(fenceHolders, offset, size) : GetFences(fenceHolders);
|
||||||
Span<Fence> fences = stackalloc Fence[count];
|
Span<Fence> fences = stackalloc Fence[count];
|
||||||
|
|
||||||
int fenceCount = 0;
|
int fenceCount = 0;
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < fences.Length; i++)
|
||||||
{
|
{
|
||||||
if (fenceHolders[i].TryGet(out Fence fence))
|
if (fenceHolders[i].TryGet(out Fence fence))
|
||||||
{
|
{
|
||||||
|
@ -180,9 +180,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
pipeline.LogicOpEnable = state.LogicOpEnable;
|
pipeline.LogicOpEnable = state.LogicOpEnable;
|
||||||
pipeline.LogicOp = state.LogicOp.Convert();
|
pipeline.LogicOp = state.LogicOp.Convert();
|
||||||
|
|
||||||
pipeline.MinDepthBounds = 0f; // Not implemented.
|
|
||||||
pipeline.MaxDepthBounds = 0f; // Not implemented.
|
|
||||||
|
|
||||||
pipeline.PatchControlPoints = state.PatchControlPoints;
|
pipeline.PatchControlPoints = state.PatchControlPoints;
|
||||||
pipeline.PolygonMode = PolygonMode.Fill; // Not implemented.
|
pipeline.PolygonMode = PolygonMode.Fill; // Not implemented.
|
||||||
pipeline.PrimitiveRestartEnable = state.PrimitiveRestartEnable;
|
pipeline.PrimitiveRestartEnable = state.PrimitiveRestartEnable;
|
||||||
@ -208,17 +205,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
pipeline.StencilFrontPassOp = state.StencilTest.FrontDpPass.Convert();
|
pipeline.StencilFrontPassOp = state.StencilTest.FrontDpPass.Convert();
|
||||||
pipeline.StencilFrontDepthFailOp = state.StencilTest.FrontDpFail.Convert();
|
pipeline.StencilFrontDepthFailOp = state.StencilTest.FrontDpFail.Convert();
|
||||||
pipeline.StencilFrontCompareOp = state.StencilTest.FrontFunc.Convert();
|
pipeline.StencilFrontCompareOp = state.StencilTest.FrontFunc.Convert();
|
||||||
pipeline.StencilFrontCompareMask = 0;
|
|
||||||
pipeline.StencilFrontWriteMask = 0;
|
|
||||||
pipeline.StencilFrontReference = 0;
|
|
||||||
|
|
||||||
pipeline.StencilBackFailOp = state.StencilTest.BackSFail.Convert();
|
pipeline.StencilBackFailOp = state.StencilTest.BackSFail.Convert();
|
||||||
pipeline.StencilBackPassOp = state.StencilTest.BackDpPass.Convert();
|
pipeline.StencilBackPassOp = state.StencilTest.BackDpPass.Convert();
|
||||||
pipeline.StencilBackDepthFailOp = state.StencilTest.BackDpFail.Convert();
|
pipeline.StencilBackDepthFailOp = state.StencilTest.BackDpFail.Convert();
|
||||||
pipeline.StencilBackCompareOp = state.StencilTest.BackFunc.Convert();
|
pipeline.StencilBackCompareOp = state.StencilTest.BackFunc.Convert();
|
||||||
pipeline.StencilBackCompareMask = 0;
|
|
||||||
pipeline.StencilBackWriteMask = 0;
|
|
||||||
pipeline.StencilBackReference = 0;
|
|
||||||
|
|
||||||
pipeline.StencilTestEnable = state.StencilTest.TestEnable;
|
pipeline.StencilTestEnable = state.StencilTest.TestEnable;
|
||||||
|
|
||||||
|
@ -71,244 +71,232 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
set => Internal.Id4 = (Internal.Id4 & 0xFFFFFFFF) | ((ulong)value << 32);
|
set => Internal.Id4 = (Internal.Id4 & 0xFFFFFFFF) | ((ulong)value << 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float MinDepthBounds
|
|
||||||
{
|
|
||||||
readonly get => BitConverter.Int32BitsToSingle((int)((Internal.Id5 >> 0) & 0xFFFFFFFF));
|
|
||||||
set => Internal.Id5 = (Internal.Id5 & 0xFFFFFFFF00000000) | ((ulong)(uint)BitConverter.SingleToInt32Bits(value) << 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public float MaxDepthBounds
|
|
||||||
{
|
|
||||||
readonly get => BitConverter.Int32BitsToSingle((int)((Internal.Id5 >> 32) & 0xFFFFFFFF));
|
|
||||||
set => Internal.Id5 = (Internal.Id5 & 0xFFFFFFFF) | ((ulong)(uint)BitConverter.SingleToInt32Bits(value) << 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PolygonMode PolygonMode
|
public PolygonMode PolygonMode
|
||||||
{
|
{
|
||||||
readonly get => (PolygonMode)((Internal.Id6 >> 0) & 0x3FFFFFFF);
|
readonly get => (PolygonMode)((Internal.Id5 >> 0) & 0x3FFFFFFF);
|
||||||
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFC0000000) | ((ulong)value << 0);
|
set => Internal.Id5 = (Internal.Id5 & 0xFFFFFFFFC0000000) | ((ulong)value << 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint StagesCount
|
public uint StagesCount
|
||||||
{
|
{
|
||||||
readonly get => (byte)((Internal.Id6 >> 30) & 0xFF);
|
readonly get => (byte)((Internal.Id5 >> 30) & 0xFF);
|
||||||
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFC03FFFFFFF) | ((ulong)value << 30);
|
set => Internal.Id5 = (Internal.Id5 & 0xFFFFFFC03FFFFFFF) | ((ulong)value << 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint VertexAttributeDescriptionsCount
|
public uint VertexAttributeDescriptionsCount
|
||||||
{
|
{
|
||||||
readonly get => (byte)((Internal.Id6 >> 38) & 0xFF);
|
readonly get => (byte)((Internal.Id5 >> 38) & 0xFF);
|
||||||
set => Internal.Id6 = (Internal.Id6 & 0xFFFFC03FFFFFFFFF) | ((ulong)value << 38);
|
set => Internal.Id5 = (Internal.Id5 & 0xFFFFC03FFFFFFFFF) | ((ulong)value << 38);
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint VertexBindingDescriptionsCount
|
public uint VertexBindingDescriptionsCount
|
||||||
{
|
{
|
||||||
readonly get => (byte)((Internal.Id6 >> 46) & 0xFF);
|
readonly get => (byte)((Internal.Id5 >> 46) & 0xFF);
|
||||||
set => Internal.Id6 = (Internal.Id6 & 0xFFC03FFFFFFFFFFF) | ((ulong)value << 46);
|
set => Internal.Id5 = (Internal.Id5 & 0xFFC03FFFFFFFFFFF) | ((ulong)value << 46);
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint ViewportsCount
|
public uint ViewportsCount
|
||||||
{
|
{
|
||||||
readonly get => (byte)((Internal.Id6 >> 54) & 0xFF);
|
readonly get => (byte)((Internal.Id5 >> 54) & 0xFF);
|
||||||
set => Internal.Id6 = (Internal.Id6 & 0xC03FFFFFFFFFFFFF) | ((ulong)value << 54);
|
set => Internal.Id5 = (Internal.Id5 & 0xC03FFFFFFFFFFFFF) | ((ulong)value << 54);
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint ScissorsCount
|
public uint ScissorsCount
|
||||||
{
|
{
|
||||||
readonly get => (byte)((Internal.Id7 >> 0) & 0xFF);
|
readonly get => (byte)((Internal.Id6 >> 0) & 0xFF);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFFFFFFFF00) | ((ulong)value << 0);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFFFFFFF00) | ((ulong)value << 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint ColorBlendAttachmentStateCount
|
public uint ColorBlendAttachmentStateCount
|
||||||
{
|
{
|
||||||
readonly get => (byte)((Internal.Id7 >> 8) & 0xFF);
|
readonly get => (byte)((Internal.Id6 >> 8) & 0xFF);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFFFFFF00FF) | ((ulong)value << 8);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFFFFF00FF) | ((ulong)value << 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PrimitiveTopology Topology
|
public PrimitiveTopology Topology
|
||||||
{
|
{
|
||||||
readonly get => (PrimitiveTopology)((Internal.Id7 >> 16) & 0xF);
|
readonly get => (PrimitiveTopology)((Internal.Id6 >> 16) & 0xF);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFFFFF0FFFF) | ((ulong)value << 16);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFFFF0FFFF) | ((ulong)value << 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LogicOp LogicOp
|
public LogicOp LogicOp
|
||||||
{
|
{
|
||||||
readonly get => (LogicOp)((Internal.Id7 >> 20) & 0xF);
|
readonly get => (LogicOp)((Internal.Id6 >> 20) & 0xF);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFFFF0FFFFF) | ((ulong)value << 20);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFFF0FFFFF) | ((ulong)value << 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompareOp DepthCompareOp
|
public CompareOp DepthCompareOp
|
||||||
{
|
{
|
||||||
readonly get => (CompareOp)((Internal.Id7 >> 24) & 0x7);
|
readonly get => (CompareOp)((Internal.Id6 >> 24) & 0x7);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFFF8FFFFFF) | ((ulong)value << 24);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFF8FFFFFF) | ((ulong)value << 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
public StencilOp StencilFrontFailOp
|
public StencilOp StencilFrontFailOp
|
||||||
{
|
{
|
||||||
readonly get => (StencilOp)((Internal.Id7 >> 27) & 0x7);
|
readonly get => (StencilOp)((Internal.Id6 >> 27) & 0x7);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFFC7FFFFFF) | ((ulong)value << 27);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFC7FFFFFF) | ((ulong)value << 27);
|
||||||
}
|
}
|
||||||
|
|
||||||
public StencilOp StencilFrontPassOp
|
public StencilOp StencilFrontPassOp
|
||||||
{
|
{
|
||||||
readonly get => (StencilOp)((Internal.Id7 >> 30) & 0x7);
|
readonly get => (StencilOp)((Internal.Id6 >> 30) & 0x7);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFE3FFFFFFF) | ((ulong)value << 30);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFE3FFFFFFF) | ((ulong)value << 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
public StencilOp StencilFrontDepthFailOp
|
public StencilOp StencilFrontDepthFailOp
|
||||||
{
|
{
|
||||||
readonly get => (StencilOp)((Internal.Id7 >> 33) & 0x7);
|
readonly get => (StencilOp)((Internal.Id6 >> 33) & 0x7);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFF1FFFFFFFF) | ((ulong)value << 33);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFF1FFFFFFFF) | ((ulong)value << 33);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompareOp StencilFrontCompareOp
|
public CompareOp StencilFrontCompareOp
|
||||||
{
|
{
|
||||||
readonly get => (CompareOp)((Internal.Id7 >> 36) & 0x7);
|
readonly get => (CompareOp)((Internal.Id6 >> 36) & 0x7);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFF8FFFFFFFFF) | ((ulong)value << 36);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFF8FFFFFFFFF) | ((ulong)value << 36);
|
||||||
}
|
}
|
||||||
|
|
||||||
public StencilOp StencilBackFailOp
|
public StencilOp StencilBackFailOp
|
||||||
{
|
{
|
||||||
readonly get => (StencilOp)((Internal.Id7 >> 39) & 0x7);
|
readonly get => (StencilOp)((Internal.Id6 >> 39) & 0x7);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFC7FFFFFFFFF) | ((ulong)value << 39);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFC7FFFFFFFFF) | ((ulong)value << 39);
|
||||||
}
|
}
|
||||||
|
|
||||||
public StencilOp StencilBackPassOp
|
public StencilOp StencilBackPassOp
|
||||||
{
|
{
|
||||||
readonly get => (StencilOp)((Internal.Id7 >> 42) & 0x7);
|
readonly get => (StencilOp)((Internal.Id6 >> 42) & 0x7);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFE3FFFFFFFFFF) | ((ulong)value << 42);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFFFE3FFFFFFFFFF) | ((ulong)value << 42);
|
||||||
}
|
}
|
||||||
|
|
||||||
public StencilOp StencilBackDepthFailOp
|
public StencilOp StencilBackDepthFailOp
|
||||||
{
|
{
|
||||||
readonly get => (StencilOp)((Internal.Id7 >> 45) & 0x7);
|
readonly get => (StencilOp)((Internal.Id6 >> 45) & 0x7);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFF1FFFFFFFFFFF) | ((ulong)value << 45);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFFF1FFFFFFFFFFF) | ((ulong)value << 45);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompareOp StencilBackCompareOp
|
public CompareOp StencilBackCompareOp
|
||||||
{
|
{
|
||||||
readonly get => (CompareOp)((Internal.Id7 >> 48) & 0x7);
|
readonly get => (CompareOp)((Internal.Id6 >> 48) & 0x7);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFF8FFFFFFFFFFFF) | ((ulong)value << 48);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFF8FFFFFFFFFFFF) | ((ulong)value << 48);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CullModeFlags CullMode
|
public CullModeFlags CullMode
|
||||||
{
|
{
|
||||||
readonly get => (CullModeFlags)((Internal.Id7 >> 51) & 0x3);
|
readonly get => (CullModeFlags)((Internal.Id6 >> 51) & 0x3);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFE7FFFFFFFFFFFF) | ((ulong)value << 51);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFE7FFFFFFFFFFFF) | ((ulong)value << 51);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool PrimitiveRestartEnable
|
public bool PrimitiveRestartEnable
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id7 >> 53) & 0x1) != 0UL;
|
readonly get => ((Internal.Id6 >> 53) & 0x1) != 0UL;
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFDFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 53);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFDFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 53);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DepthClampEnable
|
public bool DepthClampEnable
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id7 >> 54) & 0x1) != 0UL;
|
readonly get => ((Internal.Id6 >> 54) & 0x1) != 0UL;
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFBFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 54);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFBFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 54);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool RasterizerDiscardEnable
|
public bool RasterizerDiscardEnable
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id7 >> 55) & 0x1) != 0UL;
|
readonly get => ((Internal.Id6 >> 55) & 0x1) != 0UL;
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFF7FFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 55);
|
set => Internal.Id6 = (Internal.Id6 & 0xFF7FFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 55);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FrontFace FrontFace
|
public FrontFace FrontFace
|
||||||
{
|
{
|
||||||
readonly get => (FrontFace)((Internal.Id7 >> 56) & 0x1);
|
readonly get => (FrontFace)((Internal.Id6 >> 56) & 0x1);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFEFFFFFFFFFFFFFF) | ((ulong)value << 56);
|
set => Internal.Id6 = (Internal.Id6 & 0xFEFFFFFFFFFFFFFF) | ((ulong)value << 56);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DepthBiasEnable
|
public bool DepthBiasEnable
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id7 >> 57) & 0x1) != 0UL;
|
readonly get => ((Internal.Id6 >> 57) & 0x1) != 0UL;
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFDFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 57);
|
set => Internal.Id6 = (Internal.Id6 & 0xFDFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 57);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DepthTestEnable
|
public bool DepthTestEnable
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id7 >> 58) & 0x1) != 0UL;
|
readonly get => ((Internal.Id6 >> 58) & 0x1) != 0UL;
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFBFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 58);
|
set => Internal.Id6 = (Internal.Id6 & 0xFBFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 58);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DepthWriteEnable
|
public bool DepthWriteEnable
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id7 >> 59) & 0x1) != 0UL;
|
readonly get => ((Internal.Id6 >> 59) & 0x1) != 0UL;
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xF7FFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 59);
|
set => Internal.Id6 = (Internal.Id6 & 0xF7FFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 59);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DepthBoundsTestEnable
|
public bool DepthBoundsTestEnable
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id7 >> 60) & 0x1) != 0UL;
|
readonly get => ((Internal.Id6 >> 60) & 0x1) != 0UL;
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xEFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 60);
|
set => Internal.Id6 = (Internal.Id6 & 0xEFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool StencilTestEnable
|
public bool StencilTestEnable
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id7 >> 61) & 0x1) != 0UL;
|
readonly get => ((Internal.Id6 >> 61) & 0x1) != 0UL;
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xDFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 61);
|
set => Internal.Id6 = (Internal.Id6 & 0xDFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 61);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool LogicOpEnable
|
public bool LogicOpEnable
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id7 >> 62) & 0x1) != 0UL;
|
readonly get => ((Internal.Id6 >> 62) & 0x1) != 0UL;
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xBFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 62);
|
set => Internal.Id6 = (Internal.Id6 & 0xBFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 62);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasDepthStencil
|
public bool HasDepthStencil
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id7 >> 63) & 0x1) != 0UL;
|
readonly get => ((Internal.Id6 >> 63) & 0x1) != 0UL;
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0x7FFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 63);
|
set => Internal.Id6 = (Internal.Id6 & 0x7FFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 63);
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint PatchControlPoints
|
public uint PatchControlPoints
|
||||||
{
|
{
|
||||||
readonly get => (uint)((Internal.Id8 >> 0) & 0xFFFFFFFF);
|
readonly get => (uint)((Internal.Id7 >> 0) & 0xFFFFFFFF);
|
||||||
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFF00000000) | ((ulong)value << 0);
|
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFF00000000) | ((ulong)value << 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint SamplesCount
|
public uint SamplesCount
|
||||||
{
|
{
|
||||||
readonly get => (uint)((Internal.Id8 >> 32) & 0xFFFFFFFF);
|
readonly get => (uint)((Internal.Id7 >> 32) & 0xFFFFFFFF);
|
||||||
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFF) | ((ulong)value << 32);
|
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFF) | ((ulong)value << 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AlphaToCoverageEnable
|
public bool AlphaToCoverageEnable
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id9 >> 0) & 0x1) != 0UL;
|
readonly get => ((Internal.Id8 >> 0) & 0x1) != 0UL;
|
||||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFFE) | ((value ? 1UL : 0UL) << 0);
|
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFFE) | ((value ? 1UL : 0UL) << 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AlphaToOneEnable
|
public bool AlphaToOneEnable
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id9 >> 1) & 0x1) != 0UL;
|
readonly get => ((Internal.Id8 >> 1) & 0x1) != 0UL;
|
||||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFFD) | ((value ? 1UL : 0UL) << 1);
|
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFFD) | ((value ? 1UL : 0UL) << 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AdvancedBlendSrcPreMultiplied
|
public bool AdvancedBlendSrcPreMultiplied
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id9 >> 2) & 0x1) != 0UL;
|
readonly get => ((Internal.Id8 >> 2) & 0x1) != 0UL;
|
||||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFFB) | ((value ? 1UL : 0UL) << 2);
|
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFFB) | ((value ? 1UL : 0UL) << 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AdvancedBlendDstPreMultiplied
|
public bool AdvancedBlendDstPreMultiplied
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id9 >> 3) & 0x1) != 0UL;
|
readonly get => ((Internal.Id8 >> 3) & 0x1) != 0UL;
|
||||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFF7) | ((value ? 1UL : 0UL) << 3);
|
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFF7) | ((value ? 1UL : 0UL) << 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlendOverlapEXT AdvancedBlendOverlap
|
public BlendOverlapEXT AdvancedBlendOverlap
|
||||||
{
|
{
|
||||||
readonly get => (BlendOverlapEXT)((Internal.Id9 >> 4) & 0x3);
|
readonly get => (BlendOverlapEXT)((Internal.Id8 >> 4) & 0x3);
|
||||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFCF) | ((ulong)value << 4);
|
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFCF) | ((ulong)value << 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DepthMode
|
public bool DepthMode
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id9 >> 6) & 0x1) != 0UL;
|
readonly get => ((Internal.Id8 >> 6) & 0x1) != 0UL;
|
||||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFBF) | ((value ? 1UL : 0UL) << 6);
|
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFBF) | ((value ? 1UL : 0UL) << 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasTessellationControlShader;
|
public bool HasTessellationControlShader;
|
||||||
@ -408,8 +396,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions = &Internal.VertexAttributeDescriptions[0])
|
fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions = &Internal.VertexAttributeDescriptions[0])
|
||||||
fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions2 = &_vertexAttributeDescriptions2[0])
|
fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions2 = &_vertexAttributeDescriptions2[0])
|
||||||
fixed (VertexInputBindingDescription* pVertexBindingDescriptions = &Internal.VertexBindingDescriptions[0])
|
fixed (VertexInputBindingDescription* pVertexBindingDescriptions = &Internal.VertexBindingDescriptions[0])
|
||||||
fixed (Viewport* pViewports = &Internal.Viewports[0])
|
|
||||||
fixed (Rect2D* pScissors = &Internal.Scissors[0])
|
|
||||||
fixed (PipelineColorBlendAttachmentState* pColorBlendAttachmentState = &Internal.ColorBlendAttachmentState[0])
|
fixed (PipelineColorBlendAttachmentState* pColorBlendAttachmentState = &Internal.ColorBlendAttachmentState[0])
|
||||||
{
|
{
|
||||||
var vertexInputState = new PipelineVertexInputStateCreateInfo
|
var vertexInputState = new PipelineVertexInputStateCreateInfo
|
||||||
@ -472,18 +458,13 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
CullMode = CullMode,
|
CullMode = CullMode,
|
||||||
FrontFace = FrontFace,
|
FrontFace = FrontFace,
|
||||||
DepthBiasEnable = DepthBiasEnable,
|
DepthBiasEnable = DepthBiasEnable,
|
||||||
DepthBiasClamp = DepthBiasClamp,
|
|
||||||
DepthBiasConstantFactor = DepthBiasConstantFactor,
|
|
||||||
DepthBiasSlopeFactor = DepthBiasSlopeFactor,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var viewportState = new PipelineViewportStateCreateInfo
|
var viewportState = new PipelineViewportStateCreateInfo
|
||||||
{
|
{
|
||||||
SType = StructureType.PipelineViewportStateCreateInfo,
|
SType = StructureType.PipelineViewportStateCreateInfo,
|
||||||
ViewportCount = ViewportsCount,
|
ViewportCount = ViewportsCount,
|
||||||
PViewports = pViewports,
|
|
||||||
ScissorCount = ScissorsCount,
|
ScissorCount = ScissorsCount,
|
||||||
PScissors = pScissors,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (gd.Capabilities.SupportsDepthClipControl)
|
if (gd.Capabilities.SupportsDepthClipControl)
|
||||||
@ -511,19 +492,13 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
StencilFrontFailOp,
|
StencilFrontFailOp,
|
||||||
StencilFrontPassOp,
|
StencilFrontPassOp,
|
||||||
StencilFrontDepthFailOp,
|
StencilFrontDepthFailOp,
|
||||||
StencilFrontCompareOp,
|
StencilFrontCompareOp);
|
||||||
StencilFrontCompareMask,
|
|
||||||
StencilFrontWriteMask,
|
|
||||||
StencilFrontReference);
|
|
||||||
|
|
||||||
var stencilBack = new StencilOpState(
|
var stencilBack = new StencilOpState(
|
||||||
StencilBackFailOp,
|
StencilBackFailOp,
|
||||||
StencilBackPassOp,
|
StencilBackPassOp,
|
||||||
StencilBackDepthFailOp,
|
StencilBackDepthFailOp,
|
||||||
StencilBackCompareOp,
|
StencilBackCompareOp);
|
||||||
StencilBackCompareMask,
|
|
||||||
StencilBackWriteMask,
|
|
||||||
StencilBackReference);
|
|
||||||
|
|
||||||
var depthStencilState = new PipelineDepthStencilStateCreateInfo
|
var depthStencilState = new PipelineDepthStencilStateCreateInfo
|
||||||
{
|
{
|
||||||
@ -531,12 +506,10 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
DepthTestEnable = DepthTestEnable,
|
DepthTestEnable = DepthTestEnable,
|
||||||
DepthWriteEnable = DepthWriteEnable,
|
DepthWriteEnable = DepthWriteEnable,
|
||||||
DepthCompareOp = DepthCompareOp,
|
DepthCompareOp = DepthCompareOp,
|
||||||
DepthBoundsTestEnable = DepthBoundsTestEnable,
|
DepthBoundsTestEnable = false,
|
||||||
StencilTestEnable = StencilTestEnable,
|
StencilTestEnable = StencilTestEnable,
|
||||||
Front = stencilFront,
|
Front = stencilFront,
|
||||||
Back = stencilBack,
|
Back = stencilBack,
|
||||||
MinDepthBounds = MinDepthBounds,
|
|
||||||
MaxDepthBounds = MaxDepthBounds,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
uint blendEnables = 0;
|
uint blendEnables = 0;
|
||||||
@ -591,22 +564,21 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState;
|
bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState;
|
||||||
int dynamicStatesCount = supportsExtDynamicState ? 9 : 8;
|
int dynamicStatesCount = supportsExtDynamicState ? 8 : 7;
|
||||||
|
|
||||||
DynamicState* dynamicStates = stackalloc DynamicState[dynamicStatesCount];
|
DynamicState* dynamicStates = stackalloc DynamicState[dynamicStatesCount];
|
||||||
|
|
||||||
dynamicStates[0] = DynamicState.Viewport;
|
dynamicStates[0] = DynamicState.Viewport;
|
||||||
dynamicStates[1] = DynamicState.Scissor;
|
dynamicStates[1] = DynamicState.Scissor;
|
||||||
dynamicStates[2] = DynamicState.DepthBias;
|
dynamicStates[2] = DynamicState.DepthBias;
|
||||||
dynamicStates[3] = DynamicState.DepthBounds;
|
dynamicStates[3] = DynamicState.StencilCompareMask;
|
||||||
dynamicStates[4] = DynamicState.StencilCompareMask;
|
dynamicStates[4] = DynamicState.StencilWriteMask;
|
||||||
dynamicStates[5] = DynamicState.StencilWriteMask;
|
dynamicStates[5] = DynamicState.StencilReference;
|
||||||
dynamicStates[6] = DynamicState.StencilReference;
|
dynamicStates[6] = DynamicState.BlendConstants;
|
||||||
dynamicStates[7] = DynamicState.BlendConstants;
|
|
||||||
|
|
||||||
if (supportsExtDynamicState)
|
if (supportsExtDynamicState)
|
||||||
{
|
{
|
||||||
dynamicStates[8] = DynamicState.VertexInputBindingStrideExt;
|
dynamicStates[7] = DynamicState.VertexInputBindingStrideExt;
|
||||||
}
|
}
|
||||||
|
|
||||||
var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo
|
var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo
|
||||||
@ -632,7 +604,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
PDynamicState = &pipelineDynamicStateCreateInfo,
|
PDynamicState = &pipelineDynamicStateCreateInfo,
|
||||||
Layout = PipelineLayout,
|
Layout = PipelineLayout,
|
||||||
RenderPass = renderPass,
|
RenderPass = renderPass,
|
||||||
BasePipelineIndex = -1,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Result result = gd.Api.CreateGraphicsPipelines(device, cache, 1, &pipelineCreateInfo, null, &pipelineHandle);
|
Result result = gd.Api.CreateGraphicsPipelines(device, cache, 1, &pipelineCreateInfo, null, &pipelineHandle);
|
||||||
|
@ -17,20 +17,17 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
public ulong Id4;
|
public ulong Id4;
|
||||||
public ulong Id5;
|
public ulong Id5;
|
||||||
public ulong Id6;
|
public ulong Id6;
|
||||||
|
|
||||||
public ulong Id7;
|
public ulong Id7;
|
||||||
|
|
||||||
public ulong Id8;
|
public ulong Id8;
|
||||||
public ulong Id9;
|
|
||||||
|
|
||||||
private readonly uint VertexAttributeDescriptionsCount => (byte)((Id6 >> 38) & 0xFF);
|
private readonly uint VertexAttributeDescriptionsCount => (byte)((Id5 >> 38) & 0xFF);
|
||||||
private readonly uint VertexBindingDescriptionsCount => (byte)((Id6 >> 46) & 0xFF);
|
private readonly uint VertexBindingDescriptionsCount => (byte)((Id5 >> 46) & 0xFF);
|
||||||
private readonly uint ColorBlendAttachmentStateCount => (byte)((Id7 >> 8) & 0xFF);
|
private readonly uint ColorBlendAttachmentStateCount => (byte)((Id6 >> 8) & 0xFF);
|
||||||
private readonly bool HasDepthStencil => ((Id7 >> 63) & 0x1) != 0UL;
|
private readonly bool HasDepthStencil => ((Id6 >> 63) & 0x1) != 0UL;
|
||||||
|
|
||||||
public Array32<VertexInputAttributeDescription> VertexAttributeDescriptions;
|
public Array32<VertexInputAttributeDescription> VertexAttributeDescriptions;
|
||||||
public Array33<VertexInputBindingDescription> VertexBindingDescriptions;
|
public Array33<VertexInputBindingDescription> VertexBindingDescriptions;
|
||||||
public Array16<Viewport> Viewports;
|
|
||||||
public Array16<Rect2D> Scissors;
|
|
||||||
public Array8<PipelineColorBlendAttachmentState> ColorBlendAttachmentState;
|
public Array8<PipelineColorBlendAttachmentState> ColorBlendAttachmentState;
|
||||||
public Array9<Format> AttachmentFormats;
|
public Array9<Format> AttachmentFormats;
|
||||||
public uint AttachmentIntegerFormatMask;
|
public uint AttachmentIntegerFormatMask;
|
||||||
@ -45,7 +42,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
if (!Unsafe.As<ulong, Vector256<byte>>(ref Id0).Equals(Unsafe.As<ulong, Vector256<byte>>(ref other.Id0)) ||
|
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 Id4).Equals(Unsafe.As<ulong, Vector256<byte>>(ref other.Id4)) ||
|
||||||
!Unsafe.As<ulong, Vector128<byte>>(ref Id8).Equals(Unsafe.As<ulong, Vector128<byte>>(ref other.Id8)))
|
!Unsafe.As<ulong, Vector128<byte>>(ref Id7).Equals(Unsafe.As<ulong, Vector128<byte>>(ref other.Id7)))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -88,8 +85,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
Id5 * 23 ^
|
Id5 * 23 ^
|
||||||
Id6 * 23 ^
|
Id6 * 23 ^
|
||||||
Id7 * 23 ^
|
Id7 * 23 ^
|
||||||
Id8 * 23 ^
|
Id8 * 23;
|
||||||
Id9 * 23;
|
|
||||||
|
|
||||||
for (int i = 0; i < (int)VertexAttributeDescriptionsCount; i++)
|
for (int i = 0; i < (int)VertexAttributeDescriptionsCount; i++)
|
||||||
{
|
{
|
||||||
|
@ -233,7 +233,7 @@ namespace Ryujinx.UI.Windows
|
|||||||
reader.ReadInt64(); // Padding
|
reader.ReadInt64(); // Padding
|
||||||
|
|
||||||
byte[] input = new byte[stream.Length - stream.Position];
|
byte[] input = new byte[stream.Length - stream.Position];
|
||||||
stream.Read(input, 0, input.Length);
|
stream.ReadExactly(input, 0, input.Length);
|
||||||
|
|
||||||
long inputOffset = 0;
|
long inputOffset = 0;
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ namespace Ryujinx.UI.App.Common
|
|||||||
Stream resourceStream = Assembly.GetCallingAssembly().GetManifestResourceStream(resourceName);
|
Stream resourceStream = Assembly.GetCallingAssembly().GetManifestResourceStream(resourceName);
|
||||||
byte[] resourceByteArray = new byte[resourceStream.Length];
|
byte[] resourceByteArray = new byte[resourceStream.Length];
|
||||||
|
|
||||||
resourceStream.Read(resourceByteArray);
|
resourceStream.ReadExactly(resourceByteArray);
|
||||||
|
|
||||||
return resourceByteArray;
|
return resourceByteArray;
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
reader.ReadInt64(); // Padding
|
reader.ReadInt64(); // Padding
|
||||||
|
|
||||||
byte[] input = new byte[stream.Length - stream.Position];
|
byte[] input = new byte[stream.Length - stream.Position];
|
||||||
stream.Read(input, 0, input.Length);
|
stream.ReadExactly(input, 0, input.Length);
|
||||||
|
|
||||||
uint inputOffset = 0;
|
uint inputOffset = 0;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user