Move solution and projects to src
This commit is contained in:
parent
cd124bda58
commit
cee7121058
3466 changed files with 55 additions and 55 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
|
||||
{
|
||||
static class IrConsts
|
||||
{
|
||||
public const int False = 0;
|
||||
public const int True = -1;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
|
||||
{
|
||||
enum OperandType
|
||||
{
|
||||
Argument,
|
||||
Constant,
|
||||
ConstantBuffer,
|
||||
Label,
|
||||
LocalVariable,
|
||||
Register,
|
||||
Undefined
|
||||
}
|
||||
}
|
|
@ -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 };
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue