Fix shaders with global memory access from unknown locations (#4029)

* Fix shaders with global memory access from unknown locations

* Shader cache version bump
This commit is contained in:
gdkchan 2022-12-05 22:09:24 -03:00 committed by GitHub
parent 8a7de35e3f
commit de06ffb0f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 67 additions and 46 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 = 4011; private const uint CodeGenVersion = 4029;
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

@ -21,10 +21,11 @@ namespace Ryujinx.Graphics.Shader.Translation
{ {
BasicBlock block = blocks[blkIndex]; BasicBlock block = blocks[blkIndex];
for (LinkedListNode<INode> node = block.Operations.First; node != null; node = node.Next) for (LinkedListNode<INode> node = block.Operations.First; node != null;)
{ {
if (node.Value is not Operation operation) if (node.Value is not Operation operation)
{ {
node = node.Next;
continue; continue;
} }
@ -43,10 +44,7 @@ namespace Ryujinx.Graphics.Shader.Translation
} }
} }
if (UsesGlobalMemory(operation.Inst)) LinkedListNode<INode> nextNode = node.Next;
{
node = RewriteGlobalAccess(node, config);
}
if (operation is TextureOperation texOp) if (operation is TextureOperation texOp)
{ {
@ -59,7 +57,15 @@ namespace Ryujinx.Graphics.Shader.Translation
node = InsertSnormNormalization(node, config); node = InsertSnormNormalization(node, config);
} }
} }
nextNode = node.Next;
} }
else if (UsesGlobalMemory(operation.Inst))
{
nextNode = RewriteGlobalAccess(node, config)?.Next ?? nextNode;
}
node = nextNode;
} }
} }
} }
@ -72,7 +78,7 @@ namespace Ryujinx.Graphics.Shader.Translation
bool isStg16Or8 = operation.Inst == Instruction.StoreGlobal16 || operation.Inst == Instruction.StoreGlobal8; bool isStg16Or8 = operation.Inst == Instruction.StoreGlobal16 || operation.Inst == Instruction.StoreGlobal8;
bool isWrite = isAtomic || operation.Inst == Instruction.StoreGlobal || isStg16Or8; bool isWrite = isAtomic || operation.Inst == Instruction.StoreGlobal || isStg16Or8;
Operation storageOp; Operation storageOp = null;
Operand PrependOperation(Instruction inst, params Operand[] sources) Operand PrependOperation(Instruction inst, params Operand[] sources)
{ {
@ -120,49 +126,56 @@ namespace Ryujinx.Graphics.Shader.Translation
sbSlot = PrependOperation(Instruction.ConditionalSelect, inRange, Const(slot), sbSlot); sbSlot = PrependOperation(Instruction.ConditionalSelect, inRange, Const(slot), sbSlot);
} }
Operand alignMask = Const(-config.GpuAccessor.QueryHostStorageBufferOffsetAlignment()); if (sbUseMask != 0)
Operand baseAddrTrunc = PrependOperation(Instruction.BitwiseAnd, sbBaseAddrLow, alignMask);
Operand byteOffset = PrependOperation(Instruction.Subtract, addrLow, baseAddrTrunc);
Operand[] sources = new Operand[operation.SourcesCount];
sources[0] = sbSlot;
if (isStg16Or8)
{ {
sources[1] = byteOffset; Operand alignMask = Const(-config.GpuAccessor.QueryHostStorageBufferOffsetAlignment());
}
else
{
sources[1] = PrependOperation(Instruction.ShiftRightU32, byteOffset, Const(2));
}
for (int index = 2; index < operation.SourcesCount; index++) Operand baseAddrTrunc = PrependOperation(Instruction.BitwiseAnd, sbBaseAddrLow, alignMask);
{ Operand byteOffset = PrependOperation(Instruction.Subtract, addrLow, baseAddrTrunc);
sources[index] = operation.GetSource(index);
}
if (isAtomic) Operand[] sources = new Operand[operation.SourcesCount];
{
Instruction inst = (operation.Inst & ~Instruction.MrMask) | Instruction.MrStorage;
storageOp = new Operation(inst, operation.Dest, sources); sources[0] = sbSlot;
}
else if (operation.Inst == Instruction.LoadGlobal) if (isStg16Or8)
{
storageOp = new Operation(Instruction.LoadStorage, operation.Dest, sources);
}
else
{
Instruction storeInst = operation.Inst switch
{ {
Instruction.StoreGlobal16 => Instruction.StoreStorage16, sources[1] = byteOffset;
Instruction.StoreGlobal8 => Instruction.StoreStorage8, }
_ => Instruction.StoreStorage else
}; {
sources[1] = PrependOperation(Instruction.ShiftRightU32, byteOffset, Const(2));
}
storageOp = new Operation(storeInst, null, sources); for (int index = 2; index < operation.SourcesCount; index++)
{
sources[index] = operation.GetSource(index);
}
if (isAtomic)
{
Instruction inst = (operation.Inst & ~Instruction.MrMask) | Instruction.MrStorage;
storageOp = new Operation(inst, operation.Dest, sources);
}
else if (operation.Inst == Instruction.LoadGlobal)
{
storageOp = new Operation(Instruction.LoadStorage, operation.Dest, sources);
}
else
{
Instruction storeInst = operation.Inst switch
{
Instruction.StoreGlobal16 => Instruction.StoreStorage16,
Instruction.StoreGlobal8 => Instruction.StoreStorage8,
_ => Instruction.StoreStorage
};
storageOp = new Operation(storeInst, null, sources);
}
}
else if (operation.Dest != null)
{
storageOp = new Operation(Instruction.Copy, operation.Dest, Const(0));
} }
for (int index = 0; index < operation.SourcesCount; index++) for (int index = 0; index < operation.SourcesCount; index++)
@ -171,10 +184,18 @@ namespace Ryujinx.Graphics.Shader.Translation
} }
LinkedListNode<INode> oldNode = node; LinkedListNode<INode> oldNode = node;
LinkedList<INode> oldNodeList = oldNode.List;
node = node.List.AddBefore(node, storageOp); if (storageOp != null)
{
node = node.List.AddBefore(node, storageOp);
}
else
{
node = null;
}
node.List.Remove(oldNode); oldNodeList.Remove(oldNode);
return node; return node;
} }