Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
c41fddd25e | |||
2ebe929fa5 |
@ -125,9 +125,18 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
||||
CompressionAlgorithm algorithm = CompressionAlgorithm.None;
|
||||
Read(ref algorithm);
|
||||
|
||||
if (algorithm == CompressionAlgorithm.Deflate)
|
||||
switch (algorithm)
|
||||
{
|
||||
_activeStream = new DeflateStream(_stream, CompressionMode.Decompress, true);
|
||||
case CompressionAlgorithm.None:
|
||||
break;
|
||||
case CompressionAlgorithm.Deflate:
|
||||
_activeStream = new DeflateStream(_stream, CompressionMode.Decompress, true);
|
||||
break;
|
||||
case CompressionAlgorithm.Brotli:
|
||||
_activeStream = new BrotliStream(_stream, CompressionMode.Decompress, true);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException($"Invalid compression algorithm \"{algorithm}\"");
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,9 +148,18 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
||||
{
|
||||
Write(ref algorithm);
|
||||
|
||||
if (algorithm == CompressionAlgorithm.Deflate)
|
||||
switch (algorithm)
|
||||
{
|
||||
_activeStream = new DeflateStream(_stream, CompressionLevel.Fastest, true);
|
||||
case CompressionAlgorithm.None:
|
||||
break;
|
||||
case CompressionAlgorithm.Deflate:
|
||||
_activeStream = new DeflateStream(_stream, CompressionLevel.Fastest, true);
|
||||
break;
|
||||
case CompressionAlgorithm.Brotli:
|
||||
_activeStream = new BrotliStream(_stream, CompressionLevel.Fastest, true);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException($"Invalid compression algorithm \"{algorithm}\"");
|
||||
}
|
||||
}
|
||||
|
||||
@ -187,6 +205,14 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
||||
}
|
||||
stream.Dispose();
|
||||
break;
|
||||
case CompressionAlgorithm.Brotli:
|
||||
stream = new BrotliStream(stream, CompressionMode.Decompress, true);
|
||||
for (int offset = 0; offset < data.Length;)
|
||||
{
|
||||
offset += stream.Read(data[offset..]);
|
||||
}
|
||||
stream.Dispose();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -210,6 +236,11 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
||||
stream.Write(data);
|
||||
stream.Dispose();
|
||||
break;
|
||||
case CompressionAlgorithm.Brotli:
|
||||
stream = new BrotliStream(stream, CompressionLevel.Fastest, true);
|
||||
stream.Write(data);
|
||||
stream.Dispose();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,5 +14,10 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
||||
/// Deflate compression (RFC 1951).
|
||||
/// </summary>
|
||||
Deflate,
|
||||
|
||||
/// <summary>
|
||||
/// Brotli compression (RFC 7932).
|
||||
/// </summary>
|
||||
Brotli,
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
||||
/// <returns>Compression algorithm</returns>
|
||||
public static CompressionAlgorithm GetCompressionAlgorithm()
|
||||
{
|
||||
return CompressionAlgorithm.Deflate;
|
||||
return CompressionAlgorithm.Brotli;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 = 6870;
|
||||
private const uint CodeGenVersion = 6852;
|
||||
|
||||
private const string SharedTocFileName = "shared.toc";
|
||||
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.
|
||||
// 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++)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
Operand nvHandle = texOp.GetSource(0);
|
||||
Operand bindlessHandle = texOp.GetSource(0);
|
||||
|
||||
if (nvHandle.AsgOp is not Operation handleOp ||
|
||||
handleOp.Inst != Instruction.Load ||
|
||||
(handleOp.StorageKind != StorageKind.Input && handleOp.StorageKind != StorageKind.StorageBuffer))
|
||||
if (bindlessHandle.AsgOp is PhiNode phi)
|
||||
{
|
||||
// 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.
|
||||
for (int srcIndex = 0; srcIndex < phi.SourcesCount; srcIndex++)
|
||||
{
|
||||
Operand phiSource = phi.GetSource(srcIndex);
|
||||
|
||||
if (phiSource.AsgOp is not PhiNode && !IsBindlessAccessAllowed(phiSource))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!IsBindlessAccessAllowed(bindlessHandle))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -80,8 +91,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
||||
Operand samplerHandle = 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.ShiftRightU32, samplerHandle, nvHandle, OperandHelper.Const(20)));
|
||||
block.Operations.AddBefore(node, new Operation(Instruction.BitwiseAnd, textureHandle, bindlessHandle, OperandHelper.Const(0xfffff)));
|
||||
block.Operations.AddBefore(node, new Operation(Instruction.ShiftRightU32, samplerHandle, bindlessHandle, OperandHelper.Const(20)));
|
||||
|
||||
int texturePoolLength = Math.Max(BindlessToArray.MinimumArrayLength, gpuAccessor.QueryTextureArrayLengthFromPool());
|
||||
|
||||
@ -130,6 +141,30 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
||||
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)
|
||||
{
|
||||
if (texOp.Inst == Instruction.TextureSample || texOp.Inst.IsTextureQuery())
|
||||
|
Reference in New Issue
Block a user