Move solution and projects to src

This commit is contained in:
TSR Berry 2023-04-08 01:22:00 +02:00 committed by Mary
parent cd124bda58
commit cee7121058
3466 changed files with 55 additions and 55 deletions

View file

@ -0,0 +1,91 @@
using System.Collections.Generic;
namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
{
class BasicBlock
{
public int Index { get; set; }
public LinkedList<INode> Operations { get; }
private BasicBlock _next;
private BasicBlock _branch;
public BasicBlock Next
{
get => _next;
set => _next = AddSuccessor(_next, value);
}
public BasicBlock Branch
{
get => _branch;
set => _branch = AddSuccessor(_branch, value);
}
public bool HasBranch => _branch != null;
public bool Reachable => Index == 0 || Predecessors.Count != 0;
public List<BasicBlock> Predecessors { get; }
public HashSet<BasicBlock> DominanceFrontiers { get; }
public BasicBlock ImmediateDominator { get; set; }
public BasicBlock()
{
Operations = new LinkedList<INode>();
Predecessors = new List<BasicBlock>();
DominanceFrontiers = new HashSet<BasicBlock>();
}
public BasicBlock(int index) : this()
{
Index = index;
}
private BasicBlock AddSuccessor(BasicBlock oldBlock, BasicBlock newBlock)
{
oldBlock?.Predecessors.Remove(this);
newBlock?.Predecessors.Add(this);
return newBlock;
}
public INode GetLastOp()
{
return Operations.Last?.Value;
}
public void Append(INode node)
{
INode lastOp = GetLastOp();
if (lastOp is Operation operation && IsControlFlowInst(operation.Inst))
{
Operations.AddBefore(Operations.Last, node);
}
else
{
Operations.AddLast(node);
}
}
private static bool IsControlFlowInst(Instruction inst)
{
switch (inst)
{
case Instruction.Branch:
case Instruction.BranchIfFalse:
case Instruction.BranchIfTrue:
case Instruction.Discard:
case Instruction.Return:
return true;
}
return false;
}
}
}

View file

@ -0,0 +1,12 @@
namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
{
class CommentNode : Operation
{
public string Comment { get; }
public CommentNode(string comment) : base(Instruction.Comment, null)
{
Comment = comment;
}
}
}

View file

@ -0,0 +1,23 @@
namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
{
class Function
{
public BasicBlock[] Blocks { get; }
public string Name { get; }
public bool ReturnsValue { get; }
public int InArgumentsCount { get; }
public int OutArgumentsCount { get; }
public Function(BasicBlock[] blocks, string name, bool returnsValue, int inArgumentsCount, int outArgumentsCount)
{
Blocks = blocks;
Name = name;
ReturnsValue = returnsValue;
InArgumentsCount = inArgumentsCount;
OutArgumentsCount = outArgumentsCount;
}
}
}

View file

@ -0,0 +1,15 @@
namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
{
interface INode
{
Operand Dest { get; set; }
int DestsCount { get; }
int SourcesCount { get; }
Operand GetDest(int index);
Operand GetSource(int index);
void SetSource(int index, Operand operand);
}
}

View file

@ -0,0 +1,178 @@
using System;
namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
{
[Flags]
enum Instruction
{
Absolute = 1,
Add,
AtomicAdd,
AtomicAnd,
AtomicCompareAndSwap,
AtomicMinS32,
AtomicMinU32,
AtomicMaxS32,
AtomicMaxU32,
AtomicOr,
AtomicSwap,
AtomicXor,
Ballot,
Barrier,
BitCount,
BitfieldExtractS32,
BitfieldExtractU32,
BitfieldInsert,
BitfieldReverse,
BitwiseAnd,
BitwiseExclusiveOr,
BitwiseNot,
BitwiseOr,
Branch,
BranchIfFalse,
BranchIfTrue,
Call,
Ceiling,
Clamp,
ClampU32,
Comment,
CompareEqual,
CompareGreater,
CompareGreaterOrEqual,
CompareGreaterOrEqualU32,
CompareGreaterU32,
CompareLess,
CompareLessOrEqual,
CompareLessOrEqualU32,
CompareLessU32,
CompareNotEqual,
ConditionalSelect,
ConvertFP32ToFP64,
ConvertFP64ToFP32,
ConvertFP32ToS32,
ConvertFP32ToU32,
ConvertFP64ToS32,
ConvertFP64ToU32,
ConvertS32ToFP32,
ConvertS32ToFP64,
ConvertU32ToFP32,
ConvertU32ToFP64,
Copy,
Cosine,
Ddx,
Ddy,
Discard,
Divide,
EmitVertex,
EndPrimitive,
ExponentB2,
FSIBegin,
FSIEnd,
FindLSB,
FindMSBS32,
FindMSBU32,
Floor,
FusedMultiplyAdd,
GroupMemoryBarrier,
ImageLoad,
ImageStore,
ImageAtomic,
IsNan,
Load,
LoadConstant,
LoadGlobal,
LoadLocal,
LoadShared,
LoadStorage,
Lod,
LogarithmB2,
LogicalAnd,
LogicalExclusiveOr,
LogicalNot,
LogicalOr,
LoopBreak,
LoopContinue,
MarkLabel,
Maximum,
MaximumU32,
MemoryBarrier,
Minimum,
MinimumU32,
Multiply,
MultiplyHighS32,
MultiplyHighU32,
Negate,
PackDouble2x32,
PackHalf2x16,
ReciprocalSquareRoot,
Return,
Round,
ShiftLeft,
ShiftRightS32,
ShiftRightU32,
Shuffle,
ShuffleDown,
ShuffleUp,
ShuffleXor,
Sine,
SquareRoot,
Store,
StoreGlobal,
StoreGlobal16,
StoreGlobal8,
StoreLocal,
StoreShared,
StoreShared16,
StoreShared8,
StoreStorage,
StoreStorage16,
StoreStorage8,
Subtract,
SwizzleAdd,
TextureSample,
TextureSize,
Truncate,
UnpackDouble2x32,
UnpackHalf2x16,
VectorExtract,
VoteAll,
VoteAllEqual,
VoteAny,
Count,
FP32 = 1 << 16,
FP64 = 1 << 17,
Mask = 0xffff
}
static class InstructionExtensions
{
public static bool IsAtomic(this Instruction inst)
{
switch (inst & Instruction.Mask)
{
case Instruction.AtomicAdd:
case Instruction.AtomicAnd:
case Instruction.AtomicCompareAndSwap:
case Instruction.AtomicMaxS32:
case Instruction.AtomicMaxU32:
case Instruction.AtomicMinS32:
case Instruction.AtomicMinU32:
case Instruction.AtomicOr:
case Instruction.AtomicSwap:
case Instruction.AtomicXor:
return true;
}
return false;
}
public static bool IsTextureQuery(this Instruction inst)
{
inst &= Instruction.Mask;
return inst == Instruction.Lod || inst == Instruction.TextureSize;
}
}
}

View file

@ -0,0 +1,51 @@
namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
{
enum IoVariable
{
Invalid,
BackColorDiffuse,
BackColorSpecular,
BaseInstance,
BaseVertex,
ClipDistance,
CtaId,
DrawIndex,
FogCoord,
FragmentCoord,
FragmentOutputColor,
FragmentOutputDepth,
FragmentOutputIsBgra, // TODO: Remove and use constant buffer access.
FrontColorDiffuse,
FrontColorSpecular,
FrontFacing,
InstanceId,
InstanceIndex,
InvocationId,
Layer,
PatchVertices,
PointCoord,
PointSize,
Position,
PrimitiveId,
SubgroupEqMask,
SubgroupGeMask,
SubgroupGtMask,
SubgroupLaneId,
SubgroupLeMask,
SubgroupLtMask,
SupportBlockViewInverse, // TODO: Remove and use constant buffer access.
SupportBlockRenderScale, // TODO: Remove and use constant buffer access.
TessellationCoord,
TessellationLevelInner,
TessellationLevelOuter,
TextureCoord,
ThreadId,
ThreadKill,
UserDefined,
VertexId,
VertexIndex,
ViewportIndex,
ViewportMask
}
}

View file

@ -0,0 +1,8 @@
namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
{
static class IrConsts
{
public const int False = 0;
public const int True = -1;
}
}

View file

@ -0,0 +1,79 @@
using Ryujinx.Graphics.Shader.Decoders;
using System;
using System.Collections.Generic;
namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
{
class Operand
{
private const int CbufSlotBits = 5;
private const int CbufSlotLsb = 32 - CbufSlotBits;
private const int CbufSlotMask = (1 << CbufSlotBits) - 1;
public OperandType Type { get; }
public int Value { get; }
public INode AsgOp { get; set; }
public HashSet<INode> UseOps { get; }
private Operand()
{
UseOps = new HashSet<INode>();
}
public Operand(OperandType type) : this()
{
Type = type;
}
public Operand(OperandType type, int value) : this()
{
Type = type;
Value = value;
}
public Operand(Register reg) : this()
{
Type = OperandType.Register;
Value = PackRegInfo(reg.Index, reg.Type);
}
public Operand(int slot, int offset) : this()
{
Type = OperandType.ConstantBuffer;
Value = PackCbufInfo(slot, offset);
}
private static int PackCbufInfo(int slot, int offset)
{
return (slot << CbufSlotLsb) | offset;
}
private static int PackRegInfo(int index, RegisterType type)
{
return ((int)type << 24) | index;
}
public int GetCbufSlot()
{
return (Value >> CbufSlotLsb) & CbufSlotMask;
}
public int GetCbufOffset()
{
return Value & ~(CbufSlotMask << CbufSlotLsb);
}
public Register GetRegister()
{
return new Register(Value & 0xffffff, (RegisterType)(Value >> 24));
}
public float AsFloat()
{
return BitConverter.Int32BitsToSingle(Value);
}
}
}

View file

@ -0,0 +1,62 @@
using Ryujinx.Graphics.Shader.Decoders;
using System;
namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
{
static class OperandHelper
{
public static Operand Argument(int value)
{
return new Operand(OperandType.Argument, value);
}
public static Operand Cbuf(int slot, int offset)
{
return new Operand(slot, offset);
}
public static Operand Const(int value)
{
return new Operand(OperandType.Constant, value);
}
public static Operand ConstF(float value)
{
return new Operand(OperandType.Constant, BitConverter.SingleToInt32Bits(value));
}
public static Operand Label()
{
return new Operand(OperandType.Label);
}
public static Operand Local()
{
return new Operand(OperandType.LocalVariable);
}
public static Operand Register(int index, RegisterType type)
{
return Register(new Register(index, type));
}
public static Operand Register(Register reg)
{
if (reg.IsRZ)
{
return Const(0);
}
else if (reg.IsPT)
{
return Const(IrConsts.True);
}
return new Operand(reg);
}
public static Operand Undef()
{
return new Operand(OperandType.Undefined);
}
}
}

View file

@ -0,0 +1,13 @@
namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
{
enum OperandType
{
Argument,
Constant,
ConstantBuffer,
Label,
LocalVariable,
Register,
Undefined
}
}

View file

@ -0,0 +1,257 @@
using System;
using System.Diagnostics;
namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
{
class Operation : INode
{
public Instruction Inst { get; private set; }
public StorageKind StorageKind { get; }
private Operand[] _dests;
public Operand Dest
{
get
{
return _dests.Length != 0 ? _dests[0] : null;
}
set
{
if (value != null && value.Type == OperandType.LocalVariable)
{
value.AsgOp = this;
}
if (value != null)
{
_dests = new[] { value };
}
else
{
_dests = Array.Empty<Operand>();
}
}
}
public int DestsCount => _dests.Length;
private Operand[] _sources;
public int SourcesCount => _sources.Length;
public int Index { get; }
private Operation(Operand[] sources)
{
// The array may be modified externally, so we store a copy.
_sources = (Operand[])sources.Clone();
for (int index = 0; index < _sources.Length; index++)
{
Operand source = _sources[index];
if (source.Type == OperandType.LocalVariable)
{
source.UseOps.Add(this);
}
}
}
public Operation(Instruction inst, int index, Operand[] dests, Operand[] sources) : this(sources)
{
Inst = inst;
Index = index;
if (dests != null)
{
// The array may be modified externally, so we store a copy.
_dests = (Operand[])dests.Clone();
for (int dstIndex = 0; dstIndex < dests.Length; dstIndex++)
{
Operand dest = dests[dstIndex];
if (dest != null && dest.Type == OperandType.LocalVariable)
{
dest.AsgOp = this;
}
}
}
else
{
_dests = Array.Empty<Operand>();
}
}
public Operation(Instruction inst, Operand dest, params Operand[] sources) : this(sources)
{
Inst = inst;
if (dest != null)
{
dest.AsgOp = this;
_dests = new[] { dest };
}
else
{
_dests = Array.Empty<Operand>();
}
}
public Operation(Instruction inst, StorageKind storageKind, Operand dest, params Operand[] sources) : this(sources)
{
Inst = inst;
StorageKind = storageKind;
if (dest != null)
{
dest.AsgOp = this;
_dests = new[] { dest };
}
else
{
_dests = Array.Empty<Operand>();
}
}
public Operation(Instruction inst, int index, Operand dest, params Operand[] sources) : this(inst, dest, sources)
{
Index = index;
}
public void AppendDests(Operand[] operands)
{
int startIndex = _dests.Length;
Array.Resize(ref _dests, startIndex + operands.Length);
for (int index = 0; index < operands.Length; index++)
{
Operand dest = operands[index];
if (dest != null && dest.Type == OperandType.LocalVariable)
{
Debug.Assert(dest.AsgOp == null);
dest.AsgOp = this;
}
_dests[startIndex + index] = dest;
}
}
public void AppendSources(Operand[] operands)
{
int startIndex = _sources.Length;
Array.Resize(ref _sources, startIndex + operands.Length);
for (int index = 0; index < operands.Length; index++)
{
Operand source = operands[index];
if (source.Type == OperandType.LocalVariable)
{
source.UseOps.Add(this);
}
_sources[startIndex + index] = source;
}
}
public Operand GetDest(int index)
{
return _dests[index];
}
public Operand GetSource(int index)
{
return _sources[index];
}
public void SetDest(int index, Operand dest)
{
Operand oldDest = _dests[index];
if (oldDest != null && oldDest.Type == OperandType.LocalVariable)
{
oldDest.AsgOp = null;
}
if (dest != null && dest.Type == OperandType.LocalVariable)
{
dest.AsgOp = this;
}
_dests[index] = dest;
}
public void SetSource(int index, Operand source)
{
Operand oldSrc = _sources[index];
if (oldSrc != null && oldSrc.Type == OperandType.LocalVariable)
{
oldSrc.UseOps.Remove(this);
}
if (source != null && source.Type == OperandType.LocalVariable)
{
source.UseOps.Add(this);
}
_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)
{
SetSource(index, null);
Operand[] newSources = new Operand[_sources.Length - 1];
Array.Copy(_sources, 0, newSources, 0, index);
Array.Copy(_sources, index + 1, newSources, index, _sources.Length - (index + 1));
_sources = newSources;
}
public void TurnIntoCopy(Operand source)
{
TurnInto(Instruction.Copy, source);
}
public void TurnInto(Instruction newInst, Operand source)
{
Inst = newInst;
foreach (Operand oldSrc in _sources)
{
if (oldSrc != null && oldSrc.Type == OperandType.LocalVariable)
{
oldSrc.UseOps.Remove(this);
}
}
if (source.Type == OperandType.LocalVariable)
{
source.UseOps.Add(this);
}
_sources = new Operand[] { source };
}
}
}

View file

@ -0,0 +1,107 @@
using System;
using System.Collections.Generic;
namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
{
class PhiNode : INode
{
private Operand _dest;
public Operand Dest
{
get => _dest;
set => _dest = AssignDest(value);
}
public int DestsCount => _dest != null ? 1 : 0;
private HashSet<BasicBlock> _blocks;
private class PhiSource
{
public BasicBlock Block { get; }
public Operand Operand { get; set; }
public PhiSource(BasicBlock block, Operand operand)
{
Block = block;
Operand = operand;
}
}
private List<PhiSource> _sources;
public int SourcesCount => _sources.Count;
public PhiNode(Operand dest)
{
_blocks = new HashSet<BasicBlock>();
_sources = new List<PhiSource>();
dest.AsgOp = this;
Dest = dest;
}
private Operand AssignDest(Operand dest)
{
if (dest != null && dest.Type == OperandType.LocalVariable)
{
dest.AsgOp = this;
}
return dest;
}
public void AddSource(BasicBlock block, Operand operand)
{
if (_blocks.Add(block))
{
if (operand.Type == OperandType.LocalVariable)
{
operand.UseOps.Add(this);
}
_sources.Add(new PhiSource(block, operand));
}
}
public Operand GetDest(int index)
{
if (index != 0)
{
throw new ArgumentOutOfRangeException(nameof(index));
}
return _dest;
}
public Operand GetSource(int index)
{
return _sources[index].Operand;
}
public BasicBlock GetBlock(int index)
{
return _sources[index].Block;
}
public void SetSource(int index, Operand source)
{
Operand oldSrc = _sources[index].Operand;
if (oldSrc != null && oldSrc.Type == OperandType.LocalVariable)
{
oldSrc.UseOps.Remove(this);
}
if (source.Type == OperandType.LocalVariable)
{
source.UseOps.Add(this);
}
_sources[index].Operand = source;
}
}
}

View file

@ -0,0 +1,39 @@
namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
{
enum StorageKind
{
None,
Input,
InputPerPatch,
Output,
OutputPerPatch,
ConstantBuffer,
StorageBuffer,
LocalMemory,
SharedMemory,
GlobalMemory
}
static class StorageKindExtensions
{
public static bool IsInputOrOutput(this StorageKind storageKind)
{
return storageKind == StorageKind.Input ||
storageKind == StorageKind.InputPerPatch ||
storageKind == StorageKind.Output ||
storageKind == StorageKind.OutputPerPatch;
}
public static bool IsOutput(this StorageKind storageKind)
{
return storageKind == StorageKind.Output ||
storageKind == StorageKind.OutputPerPatch;
}
public static bool IsPerPatch(this StorageKind storageKind)
{
return storageKind == StorageKind.InputPerPatch ||
storageKind == StorageKind.OutputPerPatch;
}
}
}

View file

@ -0,0 +1,32 @@
using System;
namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
{
[Flags]
enum TextureFlags
{
None = 0,
Bindless = 1 << 0,
Gather = 1 << 1,
Derivatives = 1 << 2,
IntCoords = 1 << 3,
LodBias = 1 << 4,
LodLevel = 1 << 5,
Offset = 1 << 6,
Offsets = 1 << 7,
Coherent = 1 << 8,
AtomicMask = 15 << 16,
Add = 0 << 16,
Minimum = 1 << 16,
Maximum = 2 << 16,
Increment = 3 << 16,
Decrement = 4 << 16,
BitwiseAnd = 5 << 16,
BitwiseOr = 6 << 16,
BitwiseXor = 7 << 16,
Swap = 8 << 16,
CAS = 9 << 16
}
}

View file

@ -0,0 +1,69 @@
namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
{
class TextureOperation : Operation
{
public const int DefaultCbufSlot = -1;
public SamplerType Type { get; set; }
public TextureFormat Format { get; set; }
public TextureFlags Flags { get; private set; }
public int CbufSlot { get; private set; }
public int Handle { get; private set; }
public TextureOperation(
Instruction inst,
SamplerType type,
TextureFormat format,
TextureFlags flags,
int cbufSlot,
int handle,
int compIndex,
Operand[] dests,
Operand[] sources) : base(inst, compIndex, dests, sources)
{
Type = type;
Format = format;
Flags = flags;
CbufSlot = cbufSlot;
Handle = handle;
}
public TextureOperation(
Instruction inst,
SamplerType type,
TextureFormat format,
TextureFlags flags,
int handle,
int compIndex,
Operand[] dests,
Operand[] sources) : this(inst, type, format, flags, DefaultCbufSlot, handle, compIndex, dests, sources)
{
}
public void TurnIntoIndexed(int handle)
{
Type |= SamplerType.Indexed;
Flags &= ~TextureFlags.Bindless;
Handle = handle;
}
public void SetHandle(int handle, int cbufSlot = DefaultCbufSlot)
{
if ((Flags & TextureFlags.Bindless) != 0)
{
Flags &= ~TextureFlags.Bindless;
RemoveSource(0);
}
CbufSlot = cbufSlot;
Handle = handle;
}
public void SetLodLevelFlag()
{
Flags |= TextureFlags.LodLevel;
}
}
}