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:
parent
8a7de35e3f
commit
de06ffb0f7
@ -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";
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user