Fix bindless 1D textures having a buffer type on the shader (#3697)

* Fix bindless 1D textures having a buffer type on the shader

* Shader cache version bump
This commit is contained in:
gdkchan 2022-09-13 03:53:55 -03:00 committed by GitHub
parent 729ff5337c
commit 66f16f4392
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 66 additions and 10 deletions

View file

@ -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 = 3644; private const uint CodeGenVersion = 3697;
private const string SharedTocFileName = "shared.toc"; private const string SharedTocFileName = "shared.toc";
private const string SharedDataFileName = "shared.data"; private const string SharedDataFileName = "shared.data";

View file

@ -16,7 +16,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
{ 0b0111, 0b1011, 0b1101, 0b1110, 0b1111, 0b0000, 0b0000, 0b0000 } { 0b0111, 0b1011, 0b1101, 0b1110, 0b1111, 0b0000, 0b0000, 0b0000 }
}; };
private const bool Sample1DAs2D = true; public const bool Sample1DAs2D = true;
private enum TexsType private enum TexsType
{ {

View file

@ -180,6 +180,18 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
_sources[index] = source; _sources[index] = source;
} }
public void InsertSource(int index, Operand source)
{
Operand[] newSources = new Operand[_sources.Length + 1];
Array.Copy(_sources, 0, newSources, 0, index);
Array.Copy(_sources, index, newSources, index + 1, _sources.Length - index);
newSources[index] = source;
_sources = newSources;
}
protected void RemoveSource(int index) protected void RemoveSource(int index)
{ {
SetSource(index, null); SetSource(index, null);

View file

@ -60,5 +60,10 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
CbufSlot = cbufSlot; CbufSlot = cbufSlot;
Handle = handle; Handle = handle;
} }
public void SetLodLevelFlag()
{
Flags |= TextureFlags.LodLevel;
}
} }
} }

View file

@ -1,4 +1,5 @@
using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.Instructions;
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using System.Collections.Generic; using System.Collections.Generic;
namespace Ryujinx.Graphics.Shader.Translation.Optimizations namespace Ryujinx.Graphics.Shader.Translation.Optimizations
@ -30,11 +31,19 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
texOp.Inst == Instruction.TextureSize) texOp.Inst == Instruction.TextureSize)
{ {
Operand bindlessHandle = Utils.FindLastOperation(texOp.GetSource(0), block); Operand bindlessHandle = Utils.FindLastOperation(texOp.GetSource(0), block);
bool rewriteSamplerType = texOp.Inst == Instruction.TextureSize;
// Some instructions do not encode an accurate sampler type:
// - Most instructions uses the same type for 1D and Buffer.
// - Query instructions may not have any type.
// For those cases, we need to try getting the type from current GPU state,
// as long bindless elimination is successful and we know where the texture descriptor is located.
bool rewriteSamplerType =
texOp.Type == SamplerType.TextureBuffer ||
texOp.Inst == Instruction.TextureSize;
if (bindlessHandle.Type == OperandType.ConstantBuffer) if (bindlessHandle.Type == OperandType.ConstantBuffer)
{ {
SetHandle(config, texOp, bindlessHandle.GetCbufOffset(), bindlessHandle.GetCbufSlot(), rewriteSamplerType); SetHandle(config, texOp, bindlessHandle.GetCbufOffset(), bindlessHandle.GetCbufSlot(), rewriteSamplerType, isImage: false);
continue; continue;
} }
@ -137,7 +146,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
texOp, texOp,
TextureHandle.PackOffsets(src0.GetCbufOffset(), ((src1.Value >> 20) & 0xfff), handleType), TextureHandle.PackOffsets(src0.GetCbufOffset(), ((src1.Value >> 20) & 0xfff), handleType),
TextureHandle.PackSlots(src0.GetCbufSlot(), 0), TextureHandle.PackSlots(src0.GetCbufSlot(), 0),
rewriteSamplerType); rewriteSamplerType,
isImage: false);
} }
else if (src1.Type == OperandType.ConstantBuffer) else if (src1.Type == OperandType.ConstantBuffer)
{ {
@ -146,7 +156,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
texOp, texOp,
TextureHandle.PackOffsets(src0.GetCbufOffset(), src1.GetCbufOffset(), handleType), TextureHandle.PackOffsets(src0.GetCbufOffset(), src1.GetCbufOffset(), handleType),
TextureHandle.PackSlots(src0.GetCbufSlot(), src1.GetCbufSlot()), TextureHandle.PackSlots(src0.GetCbufSlot(), src1.GetCbufSlot()),
rewriteSamplerType); rewriteSamplerType,
isImage: false);
} }
} }
else if (texOp.Inst == Instruction.ImageLoad || else if (texOp.Inst == Instruction.ImageLoad ||
@ -172,7 +183,9 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
} }
} }
SetHandle(config, texOp, cbufOffset, cbufSlot, false); bool rewriteSamplerType = texOp.Type == SamplerType.TextureBuffer;
SetHandle(config, texOp, cbufOffset, cbufSlot, rewriteSamplerType, isImage: true);
} }
} }
} }
@ -209,13 +222,39 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
return null; return null;
} }
private static void SetHandle(ShaderConfig config, TextureOperation texOp, int cbufOffset, int cbufSlot, bool rewriteSamplerType) private static void SetHandle(ShaderConfig config, TextureOperation texOp, int cbufOffset, int cbufSlot, bool rewriteSamplerType, bool isImage)
{ {
texOp.SetHandle(cbufOffset, cbufSlot); texOp.SetHandle(cbufOffset, cbufSlot);
if (rewriteSamplerType) if (rewriteSamplerType)
{ {
texOp.Type = config.GpuAccessor.QuerySamplerType(cbufOffset, cbufSlot); SamplerType newType = config.GpuAccessor.QuerySamplerType(cbufOffset, cbufSlot);
if (texOp.Inst.IsTextureQuery())
{
texOp.Type = newType;
}
else if (texOp.Type == SamplerType.TextureBuffer && newType == SamplerType.Texture1D)
{
int coordsCount = 1;
if (InstEmit.Sample1DAs2D)
{
newType = SamplerType.Texture2D;
texOp.InsertSource(coordsCount++, OperandHelper.Const(0));
}
if (!isImage &&
(texOp.Flags & TextureFlags.IntCoords) != 0 &&
(texOp.Flags & TextureFlags.LodLevel) == 0)
{
// IntCoords textures must always have explicit LOD.
texOp.SetLodLevelFlag();
texOp.InsertSource(coordsCount, OperandHelper.Const(0));
}
texOp.Type = newType;
}
} }
config.SetUsedTexture(texOp.Inst, texOp.Type, texOp.Format, texOp.Flags, cbufSlot, cbufOffset); config.SetUsedTexture(texOp.Inst, texOp.Type, texOp.Format, texOp.Flags, cbufSlot, cbufOffset);