diff options
| author | TSR Berry <20988865+TSRBerry@users.noreply.github.com> | 2023-04-08 01:22:00 +0200 |
|---|---|---|
| committer | Mary <thog@protonmail.com> | 2023-04-27 23:51:14 +0200 |
| commit | cee712105850ac3385cd0091a923438167433f9f (patch) | |
| tree | 4a5274b21d8b7f938c0d0ce18736d3f2993b11b1 /Ryujinx.Graphics.Shader/Instructions | |
| parent | cd124bda587ef09668a971fa1cac1c3f0cfc9f21 (diff) | |
Move solution and projects to src
Diffstat (limited to 'Ryujinx.Graphics.Shader/Instructions')
30 files changed, 0 insertions, 8904 deletions
diff --git a/Ryujinx.Graphics.Shader/Instructions/AttributeMap.cs b/Ryujinx.Graphics.Shader/Instructions/AttributeMap.cs deleted file mode 100644 index 562fb8d5..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/AttributeMap.cs +++ /dev/null @@ -1,351 +0,0 @@ -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; -using System.Collections.Generic; - -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static class AttributeMap - { - private enum StagesMask : byte - { - None = 0, - Compute = 1 << (int)ShaderStage.Compute, - Vertex = 1 << (int)ShaderStage.Vertex, - TessellationControl = 1 << (int)ShaderStage.TessellationControl, - TessellationEvaluation = 1 << (int)ShaderStage.TessellationEvaluation, - Geometry = 1 << (int)ShaderStage.Geometry, - Fragment = 1 << (int)ShaderStage.Fragment, - - Tessellation = TessellationControl | TessellationEvaluation, - VertexTessellationGeometry = Vertex | Tessellation | Geometry, - TessellationGeometryFragment = Tessellation | Geometry | Fragment, - AllGraphics = Vertex | Tessellation | Geometry | Fragment - } - - private struct AttributeEntry - { - public int BaseOffset { get; } - public AggregateType Type { get; } - public IoVariable IoVariable { get; } - public StagesMask InputMask { get; } - public StagesMask OutputMask { get; } - - public AttributeEntry( - int baseOffset, - AggregateType type, - IoVariable ioVariable, - StagesMask inputMask, - StagesMask outputMask) - { - BaseOffset = baseOffset; - Type = type; - IoVariable = ioVariable; - InputMask = inputMask; - OutputMask = outputMask; - } - } - - private static readonly IReadOnlyDictionary<int, AttributeEntry> _attributes; - private static readonly IReadOnlyDictionary<int, AttributeEntry> _attributesPerPatch; - - static AttributeMap() - { - _attributes = CreateMap(); - _attributesPerPatch = CreatePerPatchMap(); - } - - private static IReadOnlyDictionary<int, AttributeEntry> CreateMap() - { - var map = new Dictionary<int, AttributeEntry>(); - - Add(map, 0x060, AggregateType.S32, IoVariable.PrimitiveId, StagesMask.TessellationGeometryFragment, StagesMask.Geometry); - Add(map, 0x064, AggregateType.S32, IoVariable.Layer, StagesMask.Fragment, StagesMask.VertexTessellationGeometry); - Add(map, 0x068, AggregateType.S32, IoVariable.ViewportIndex, StagesMask.Fragment, StagesMask.VertexTessellationGeometry); - Add(map, 0x06c, AggregateType.FP32, IoVariable.PointSize, StagesMask.None, StagesMask.VertexTessellationGeometry); - Add(map, 0x070, AggregateType.Vector4 | AggregateType.FP32, IoVariable.Position, StagesMask.TessellationGeometryFragment, StagesMask.VertexTessellationGeometry); - Add(map, 0x080, AggregateType.Vector4 | AggregateType.FP32, IoVariable.UserDefined, StagesMask.AllGraphics, StagesMask.VertexTessellationGeometry, 32); - Add(map, 0x280, AggregateType.Vector4 | AggregateType.FP32, IoVariable.FrontColorDiffuse, StagesMask.TessellationGeometryFragment, StagesMask.VertexTessellationGeometry); - Add(map, 0x290, AggregateType.Vector4 | AggregateType.FP32, IoVariable.FrontColorSpecular, StagesMask.TessellationGeometryFragment, StagesMask.VertexTessellationGeometry); - Add(map, 0x2a0, AggregateType.Vector4 | AggregateType.FP32, IoVariable.BackColorDiffuse, StagesMask.TessellationGeometryFragment, StagesMask.VertexTessellationGeometry); - Add(map, 0x2b0, AggregateType.Vector4 | AggregateType.FP32, IoVariable.BackColorSpecular, StagesMask.TessellationGeometryFragment, StagesMask.VertexTessellationGeometry); - Add(map, 0x2c0, AggregateType.Array | AggregateType.FP32, IoVariable.ClipDistance, StagesMask.TessellationGeometryFragment, StagesMask.VertexTessellationGeometry, 8); - Add(map, 0x2e0, AggregateType.Vector2 | AggregateType.FP32, IoVariable.PointCoord, StagesMask.Fragment, StagesMask.None); - Add(map, 0x2e8, AggregateType.FP32, IoVariable.FogCoord, StagesMask.TessellationGeometryFragment, StagesMask.VertexTessellationGeometry); - Add(map, 0x2f0, AggregateType.Vector2 | AggregateType.FP32, IoVariable.TessellationCoord, StagesMask.TessellationEvaluation, StagesMask.None); - Add(map, 0x2f8, AggregateType.S32, IoVariable.InstanceId, StagesMask.Vertex, StagesMask.None); - Add(map, 0x2fc, AggregateType.S32, IoVariable.VertexId, StagesMask.Vertex, StagesMask.None); - Add(map, 0x300, AggregateType.Vector4 | AggregateType.FP32, IoVariable.TextureCoord, StagesMask.TessellationGeometryFragment, StagesMask.VertexTessellationGeometry); - Add(map, 0x3a0, AggregateType.Array | AggregateType.S32, IoVariable.ViewportMask, StagesMask.Fragment, StagesMask.VertexTessellationGeometry); - Add(map, 0x3fc, AggregateType.Bool, IoVariable.FrontFacing, StagesMask.Fragment, StagesMask.None); - - return map; - } - - private static IReadOnlyDictionary<int, AttributeEntry> CreatePerPatchMap() - { - var map = new Dictionary<int, AttributeEntry>(); - - Add(map, 0x000, AggregateType.Vector4 | AggregateType.FP32, IoVariable.TessellationLevelOuter, StagesMask.TessellationEvaluation, StagesMask.TessellationControl); - Add(map, 0x010, AggregateType.Vector2 | AggregateType.FP32, IoVariable.TessellationLevelInner, StagesMask.TessellationEvaluation, StagesMask.TessellationControl); - Add(map, 0x018, AggregateType.Vector4 | AggregateType.FP32, IoVariable.UserDefined, StagesMask.TessellationEvaluation, StagesMask.TessellationControl, 31, 0x200); - - return map; - } - - private static void Add( - Dictionary<int, AttributeEntry> attributes, - int offset, - AggregateType type, - IoVariable ioVariable, - StagesMask inputMask, - StagesMask outputMask, - int count = 1, - int upperBound = 0x400) - { - int baseOffset = offset; - - int elementsCount = GetElementCount(type); - - for (int index = 0; index < count; index++) - { - for (int elementIndex = 0; elementIndex < elementsCount; elementIndex++) - { - attributes.Add(offset, new AttributeEntry(baseOffset, type, ioVariable, inputMask, outputMask)); - - offset += 4; - - if (offset >= upperBound) - { - return; - } - } - } - } - - public static Operand GenerateAttributeLoad(EmitterContext context, Operand primVertex, int offset, bool isOutput, bool isPerPatch) - { - if (!(isPerPatch ? _attributesPerPatch : _attributes).TryGetValue(offset, out AttributeEntry entry)) - { - context.Config.GpuAccessor.Log($"Attribute offset 0x{offset:X} is not valid."); - return Const(0); - } - - StagesMask validUseMask = isOutput ? entry.OutputMask : entry.InputMask; - - if (((StagesMask)(1 << (int)context.Config.Stage) & validUseMask) == StagesMask.None) - { - context.Config.GpuAccessor.Log($"Attribute offset 0x{offset:X} ({entry.IoVariable}) is not valid for stage {context.Config.Stage}."); - return Const(0); - } - - if (!IsSupportedByHost(context.Config.GpuAccessor, context.Config.Stage, entry.IoVariable)) - { - context.Config.GpuAccessor.Log($"Attribute offset 0x{offset:X} ({entry.IoVariable}) is not supported by the host for stage {context.Config.Stage}."); - return Const(0); - } - - if (HasInvocationId(context.Config.Stage, isOutput) && !isPerPatch) - { - primVertex = context.Load(StorageKind.Input, IoVariable.InvocationId); - } - - int innerOffset = offset - entry.BaseOffset; - int innerIndex = innerOffset / 4; - - StorageKind storageKind = isPerPatch - ? (isOutput ? StorageKind.OutputPerPatch : StorageKind.InputPerPatch) - : (isOutput ? StorageKind.Output : StorageKind.Input); - IoVariable ioVariable = GetIoVariable(context.Config.Stage, in entry); - AggregateType type = GetType(context.Config, isOutput, innerIndex, in entry); - int elementCount = GetElementCount(type); - - bool isArray = type.HasFlag(AggregateType.Array); - bool hasArrayIndex = isArray || context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput); - - bool hasElementIndex = elementCount > 1; - - if (hasArrayIndex && hasElementIndex) - { - int arrayIndex = innerIndex / elementCount; - int elementIndex = innerIndex - (arrayIndex * elementCount); - - return primVertex == null || isArray - ? context.Load(storageKind, ioVariable, primVertex, Const(arrayIndex), Const(elementIndex)) - : context.Load(storageKind, ioVariable, Const(arrayIndex), primVertex, Const(elementIndex)); - } - else if (hasArrayIndex || hasElementIndex) - { - return primVertex == null || isArray || !hasArrayIndex - ? context.Load(storageKind, ioVariable, primVertex, Const(innerIndex)) - : context.Load(storageKind, ioVariable, Const(innerIndex), primVertex); - } - else - { - return context.Load(storageKind, ioVariable, primVertex); - } - } - - public static void GenerateAttributeStore(EmitterContext context, int offset, bool isPerPatch, Operand value) - { - if (!(isPerPatch ? _attributesPerPatch : _attributes).TryGetValue(offset, out AttributeEntry entry)) - { - context.Config.GpuAccessor.Log($"Attribute offset 0x{offset:X} is not valid."); - return; - } - - if (((StagesMask)(1 << (int)context.Config.Stage) & entry.OutputMask) == StagesMask.None) - { - context.Config.GpuAccessor.Log($"Attribute offset 0x{offset:X} ({entry.IoVariable}) is not valid for stage {context.Config.Stage}."); - return; - } - - if (!IsSupportedByHost(context.Config.GpuAccessor, context.Config.Stage, entry.IoVariable)) - { - context.Config.GpuAccessor.Log($"Attribute offset 0x{offset:X} ({entry.IoVariable}) is not supported by the host for stage {context.Config.Stage}."); - return; - } - - Operand invocationId = null; - - if (HasInvocationId(context.Config.Stage, isOutput: true) && !isPerPatch) - { - invocationId = context.Load(StorageKind.Input, IoVariable.InvocationId); - } - - int innerOffset = offset - entry.BaseOffset; - int innerIndex = innerOffset / 4; - - StorageKind storageKind = isPerPatch ? StorageKind.OutputPerPatch : StorageKind.Output; - IoVariable ioVariable = GetIoVariable(context.Config.Stage, in entry); - AggregateType type = GetType(context.Config, isOutput: true, innerIndex, in entry); - int elementCount = GetElementCount(type); - - bool isArray = type.HasFlag(AggregateType.Array); - bool hasArrayIndex = isArray || context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput: true); - - bool hasElementIndex = elementCount > 1; - - if (hasArrayIndex && hasElementIndex) - { - int arrayIndex = innerIndex / elementCount; - int elementIndex = innerIndex - (arrayIndex * elementCount); - - if (invocationId == null || isArray) - { - context.Store(storageKind, ioVariable, invocationId, Const(arrayIndex), Const(elementIndex), value); - } - else - { - context.Store(storageKind, ioVariable, Const(arrayIndex), invocationId, Const(elementIndex), value); - } - } - else if (hasArrayIndex || hasElementIndex) - { - if (invocationId == null || isArray || !hasArrayIndex) - { - context.Store(storageKind, ioVariable, invocationId, Const(innerIndex), value); - } - else - { - context.Store(storageKind, ioVariable, Const(innerIndex), invocationId, value); - } - } - else - { - context.Store(storageKind, ioVariable, invocationId, value); - } - } - - private static bool IsSupportedByHost(IGpuAccessor gpuAccessor, ShaderStage stage, IoVariable ioVariable) - { - if (ioVariable == IoVariable.ViewportIndex && stage != ShaderStage.Geometry && stage != ShaderStage.Fragment) - { - return gpuAccessor.QueryHostSupportsViewportIndexVertexTessellation(); - } - else if (ioVariable == IoVariable.ViewportMask) - { - return gpuAccessor.QueryHostSupportsViewportMask(); - } - - return true; - } - - public static IoVariable GetIoVariable(ShaderConfig config, int offset, out int location) - { - location = 0; - - if (!_attributes.TryGetValue(offset, out AttributeEntry entry)) - { - return IoVariable.Invalid; - } - - if (((StagesMask)(1 << (int)config.Stage) & entry.OutputMask) == StagesMask.None) - { - return IoVariable.Invalid; - } - - if (config.HasPerLocationInputOrOutput(entry.IoVariable, isOutput: true)) - { - location = (offset - entry.BaseOffset) / 16; - } - - return GetIoVariable(config.Stage, in entry); - } - - private static IoVariable GetIoVariable(ShaderStage stage, in AttributeEntry entry) - { - if (entry.IoVariable == IoVariable.Position && stage == ShaderStage.Fragment) - { - return IoVariable.FragmentCoord; - } - - return entry.IoVariable; - } - - private static AggregateType GetType(ShaderConfig config, bool isOutput, int innerIndex, in AttributeEntry entry) - { - AggregateType type = entry.Type; - - if (entry.IoVariable == IoVariable.UserDefined) - { - type = config.GetUserDefinedType(innerIndex / 4, isOutput); - } - else if (entry.IoVariable == IoVariable.FragmentOutputColor) - { - type = config.GetFragmentOutputColorType(innerIndex / 4); - } - - return type; - } - - public static bool HasPrimitiveVertex(ShaderStage stage, bool isOutput) - { - if (isOutput) - { - return false; - } - - return stage == ShaderStage.TessellationControl || - stage == ShaderStage.TessellationEvaluation || - stage == ShaderStage.Geometry; - } - - public static bool HasInvocationId(ShaderStage stage, bool isOutput) - { - return isOutput && stage == ShaderStage.TessellationControl; - } - - private static int GetElementCount(AggregateType type) - { - return (type & AggregateType.ElementCountMask) switch - { - AggregateType.Vector2 => 2, - AggregateType.Vector3 => 3, - AggregateType.Vector4 => 4, - _ => 1 - }; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs deleted file mode 100644 index 3a9e658a..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs +++ /dev/null @@ -1,379 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.Translation; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - public static void AtomCas(EmitterContext context) - { - InstAtomCas op = context.GetOp<InstAtomCas>(); - - context.Config.GpuAccessor.Log("Shader instruction AtomCas is not implemented."); - } - - public static void AtomsCas(EmitterContext context) - { - InstAtomsCas op = context.GetOp<InstAtomsCas>(); - - context.Config.GpuAccessor.Log("Shader instruction AtomsCas is not implemented."); - } - - public static void B2r(EmitterContext context) - { - InstB2r op = context.GetOp<InstB2r>(); - - context.Config.GpuAccessor.Log("Shader instruction B2r is not implemented."); - } - - public static void Bpt(EmitterContext context) - { - InstBpt op = context.GetOp<InstBpt>(); - - context.Config.GpuAccessor.Log("Shader instruction Bpt is not implemented."); - } - - public static void Cctl(EmitterContext context) - { - InstCctl op = context.GetOp<InstCctl>(); - - context.Config.GpuAccessor.Log("Shader instruction Cctl is not implemented."); - } - - public static void Cctll(EmitterContext context) - { - InstCctll op = context.GetOp<InstCctll>(); - - context.Config.GpuAccessor.Log("Shader instruction Cctll is not implemented."); - } - - public static void Cctlt(EmitterContext context) - { - InstCctlt op = context.GetOp<InstCctlt>(); - - context.Config.GpuAccessor.Log("Shader instruction Cctlt is not implemented."); - } - - public static void Cs2r(EmitterContext context) - { - InstCs2r op = context.GetOp<InstCs2r>(); - - context.Config.GpuAccessor.Log("Shader instruction Cs2r is not implemented."); - } - - public static void FchkR(EmitterContext context) - { - InstFchkR op = context.GetOp<InstFchkR>(); - - context.Config.GpuAccessor.Log("Shader instruction FchkR is not implemented."); - } - - public static void FchkI(EmitterContext context) - { - InstFchkI op = context.GetOp<InstFchkI>(); - - context.Config.GpuAccessor.Log("Shader instruction FchkI is not implemented."); - } - - public static void FchkC(EmitterContext context) - { - InstFchkC op = context.GetOp<InstFchkC>(); - - context.Config.GpuAccessor.Log("Shader instruction FchkC is not implemented."); - } - - public static void Getcrsptr(EmitterContext context) - { - InstGetcrsptr op = context.GetOp<InstGetcrsptr>(); - - context.Config.GpuAccessor.Log("Shader instruction Getcrsptr is not implemented."); - } - - public static void Getlmembase(EmitterContext context) - { - InstGetlmembase op = context.GetOp<InstGetlmembase>(); - - context.Config.GpuAccessor.Log("Shader instruction Getlmembase is not implemented."); - } - - public static void Ide(EmitterContext context) - { - InstIde op = context.GetOp<InstIde>(); - - context.Config.GpuAccessor.Log("Shader instruction Ide is not implemented."); - } - - public static void IdpR(EmitterContext context) - { - InstIdpR op = context.GetOp<InstIdpR>(); - - context.Config.GpuAccessor.Log("Shader instruction IdpR is not implemented."); - } - - public static void IdpC(EmitterContext context) - { - InstIdpC op = context.GetOp<InstIdpC>(); - - context.Config.GpuAccessor.Log("Shader instruction IdpC is not implemented."); - } - - public static void ImadspR(EmitterContext context) - { - InstImadspR op = context.GetOp<InstImadspR>(); - - context.Config.GpuAccessor.Log("Shader instruction ImadspR is not implemented."); - } - - public static void ImadspI(EmitterContext context) - { - InstImadspI op = context.GetOp<InstImadspI>(); - - context.Config.GpuAccessor.Log("Shader instruction ImadspI is not implemented."); - } - - public static void ImadspC(EmitterContext context) - { - InstImadspC op = context.GetOp<InstImadspC>(); - - context.Config.GpuAccessor.Log("Shader instruction ImadspC is not implemented."); - } - - public static void ImadspRc(EmitterContext context) - { - InstImadspRc op = context.GetOp<InstImadspRc>(); - - context.Config.GpuAccessor.Log("Shader instruction ImadspRc is not implemented."); - } - - public static void Jcal(EmitterContext context) - { - InstJcal op = context.GetOp<InstJcal>(); - - context.Config.GpuAccessor.Log("Shader instruction Jcal is not implemented."); - } - - public static void Jmp(EmitterContext context) - { - InstJmp op = context.GetOp<InstJmp>(); - - context.Config.GpuAccessor.Log("Shader instruction Jmp is not implemented."); - } - - public static void Jmx(EmitterContext context) - { - InstJmx op = context.GetOp<InstJmx>(); - - context.Config.GpuAccessor.Log("Shader instruction Jmx is not implemented."); - } - - public static void Ld(EmitterContext context) - { - InstLd op = context.GetOp<InstLd>(); - - context.Config.GpuAccessor.Log("Shader instruction Ld is not implemented."); - } - - public static void Lepc(EmitterContext context) - { - InstLepc op = context.GetOp<InstLepc>(); - - context.Config.GpuAccessor.Log("Shader instruction Lepc is not implemented."); - } - - public static void Longjmp(EmitterContext context) - { - InstLongjmp op = context.GetOp<InstLongjmp>(); - - context.Config.GpuAccessor.Log("Shader instruction Longjmp is not implemented."); - } - - public static void P2rR(EmitterContext context) - { - InstP2rR op = context.GetOp<InstP2rR>(); - - context.Config.GpuAccessor.Log("Shader instruction P2rR is not implemented."); - } - - public static void P2rI(EmitterContext context) - { - InstP2rI op = context.GetOp<InstP2rI>(); - - context.Config.GpuAccessor.Log("Shader instruction P2rI is not implemented."); - } - - public static void P2rC(EmitterContext context) - { - InstP2rC op = context.GetOp<InstP2rC>(); - - context.Config.GpuAccessor.Log("Shader instruction P2rC is not implemented."); - } - - public static void Pexit(EmitterContext context) - { - InstPexit op = context.GetOp<InstPexit>(); - - context.Config.GpuAccessor.Log("Shader instruction Pexit is not implemented."); - } - - public static void Pixld(EmitterContext context) - { - InstPixld op = context.GetOp<InstPixld>(); - - context.Config.GpuAccessor.Log("Shader instruction Pixld is not implemented."); - } - - public static void Plongjmp(EmitterContext context) - { - InstPlongjmp op = context.GetOp<InstPlongjmp>(); - - context.Config.GpuAccessor.Log("Shader instruction Plongjmp is not implemented."); - } - - public static void Pret(EmitterContext context) - { - InstPret op = context.GetOp<InstPret>(); - - context.Config.GpuAccessor.Log("Shader instruction Pret is not implemented."); - } - - public static void PrmtR(EmitterContext context) - { - InstPrmtR op = context.GetOp<InstPrmtR>(); - - context.Config.GpuAccessor.Log("Shader instruction PrmtR is not implemented."); - } - - public static void PrmtI(EmitterContext context) - { - InstPrmtI op = context.GetOp<InstPrmtI>(); - - context.Config.GpuAccessor.Log("Shader instruction PrmtI is not implemented."); - } - - public static void PrmtC(EmitterContext context) - { - InstPrmtC op = context.GetOp<InstPrmtC>(); - - context.Config.GpuAccessor.Log("Shader instruction PrmtC is not implemented."); - } - - public static void PrmtRc(EmitterContext context) - { - InstPrmtRc op = context.GetOp<InstPrmtRc>(); - - context.Config.GpuAccessor.Log("Shader instruction PrmtRc is not implemented."); - } - - public static void R2b(EmitterContext context) - { - InstR2b op = context.GetOp<InstR2b>(); - - context.Config.GpuAccessor.Log("Shader instruction R2b is not implemented."); - } - - public static void Ram(EmitterContext context) - { - InstRam op = context.GetOp<InstRam>(); - - context.Config.GpuAccessor.Log("Shader instruction Ram is not implemented."); - } - - public static void Rtt(EmitterContext context) - { - InstRtt op = context.GetOp<InstRtt>(); - - context.Config.GpuAccessor.Log("Shader instruction Rtt is not implemented."); - } - - public static void Sam(EmitterContext context) - { - InstSam op = context.GetOp<InstSam>(); - - context.Config.GpuAccessor.Log("Shader instruction Sam is not implemented."); - } - - public static void Setcrsptr(EmitterContext context) - { - InstSetcrsptr op = context.GetOp<InstSetcrsptr>(); - - context.Config.GpuAccessor.Log("Shader instruction Setcrsptr is not implemented."); - } - - public static void Setlmembase(EmitterContext context) - { - InstSetlmembase op = context.GetOp<InstSetlmembase>(); - - context.Config.GpuAccessor.Log("Shader instruction Setlmembase is not implemented."); - } - - public static void St(EmitterContext context) - { - InstSt op = context.GetOp<InstSt>(); - - context.Config.GpuAccessor.Log("Shader instruction St is not implemented."); - } - - public static void Stp(EmitterContext context) - { - InstStp op = context.GetOp<InstStp>(); - - context.Config.GpuAccessor.Log("Shader instruction Stp is not implemented."); - } - - public static void Txa(EmitterContext context) - { - InstTxa op = context.GetOp<InstTxa>(); - - context.Config.GpuAccessor.Log("Shader instruction Txa is not implemented."); - } - - public static void Vabsdiff(EmitterContext context) - { - InstVabsdiff op = context.GetOp<InstVabsdiff>(); - - context.Config.GpuAccessor.Log("Shader instruction Vabsdiff is not implemented."); - } - - public static void Vabsdiff4(EmitterContext context) - { - InstVabsdiff4 op = context.GetOp<InstVabsdiff4>(); - - context.Config.GpuAccessor.Log("Shader instruction Vabsdiff4 is not implemented."); - } - - public static void Vadd(EmitterContext context) - { - InstVadd op = context.GetOp<InstVadd>(); - - context.Config.GpuAccessor.Log("Shader instruction Vadd is not implemented."); - } - - public static void Votevtg(EmitterContext context) - { - InstVotevtg op = context.GetOp<InstVotevtg>(); - - context.Config.GpuAccessor.Log("Shader instruction Votevtg is not implemented."); - } - - public static void Vset(EmitterContext context) - { - InstVset op = context.GetOp<InstVset>(); - - context.Config.GpuAccessor.Log("Shader instruction Vset is not implemented."); - } - - public static void Vshl(EmitterContext context) - { - InstVshl op = context.GetOp<InstVshl>(); - - context.Config.GpuAccessor.Log("Shader instruction Vshl is not implemented."); - } - - public static void Vshr(EmitterContext context) - { - InstVshr op = context.GetOp<InstVshr>(); - - context.Config.GpuAccessor.Log("Shader instruction Vshr is not implemented."); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitAluHelper.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitAluHelper.cs deleted file mode 100644 index 879075ba..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitAluHelper.cs +++ /dev/null @@ -1,160 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; -using System; - -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static class InstEmitAluHelper - { - public static long GetIntMin(IDstFmt type) - { - return type switch - { - IDstFmt.U16 => ushort.MinValue, - IDstFmt.S16 => short.MinValue, - IDstFmt.U32 => uint.MinValue, - IDstFmt.S32 => int.MinValue, - _ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type.") - }; - } - - public static long GetIntMax(IDstFmt type) - { - return type switch - { - IDstFmt.U16 => ushort.MaxValue, - IDstFmt.S16 => short.MaxValue, - IDstFmt.U32 => uint.MaxValue, - IDstFmt.S32 => int.MaxValue, - _ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type.") - }; - } - - public static long GetIntMin(ISrcDstFmt type) - { - return type switch - { - ISrcDstFmt.U8 => byte.MinValue, - ISrcDstFmt.S8 => sbyte.MinValue, - ISrcDstFmt.U16 => ushort.MinValue, - ISrcDstFmt.S16 => short.MinValue, - ISrcDstFmt.U32 => uint.MinValue, - ISrcDstFmt.S32 => int.MinValue, - _ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type.") - }; - } - - public static long GetIntMax(ISrcDstFmt type) - { - return type switch - { - ISrcDstFmt.U8 => byte.MaxValue, - ISrcDstFmt.S8 => sbyte.MaxValue, - ISrcDstFmt.U16 => ushort.MaxValue, - ISrcDstFmt.S16 => short.MaxValue, - ISrcDstFmt.U32 => uint.MaxValue, - ISrcDstFmt.S32 => int.MaxValue, - _ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type.") - }; - } - - public static Operand GetPredLogicalOp(EmitterContext context, BoolOp logicOp, Operand input, Operand pred) - { - return logicOp switch - { - BoolOp.And => context.BitwiseAnd(input, pred), - BoolOp.Or => context.BitwiseOr(input, pred), - BoolOp.Xor => context.BitwiseExclusiveOr(input, pred), - _ => input - }; - } - - public static Operand Extend(EmitterContext context, Operand src, VectorSelect type) - { - return type switch - { - VectorSelect.U8B0 => ZeroExtendTo32(context, context.ShiftRightU32(src, Const(0)), 8), - VectorSelect.U8B1 => ZeroExtendTo32(context, context.ShiftRightU32(src, Const(8)), 8), - VectorSelect.U8B2 => ZeroExtendTo32(context, context.ShiftRightU32(src, Const(16)), 8), - VectorSelect.U8B3 => ZeroExtendTo32(context, context.ShiftRightU32(src, Const(24)), 8), - VectorSelect.U16H0 => ZeroExtendTo32(context, context.ShiftRightU32(src, Const(0)), 16), - VectorSelect.U16H1 => ZeroExtendTo32(context, context.ShiftRightU32(src, Const(16)), 16), - VectorSelect.S8B0 => SignExtendTo32(context, context.ShiftRightU32(src, Const(0)), 8), - VectorSelect.S8B1 => SignExtendTo32(context, context.ShiftRightU32(src, Const(8)), 8), - VectorSelect.S8B2 => SignExtendTo32(context, context.ShiftRightU32(src, Const(16)), 8), - VectorSelect.S8B3 => SignExtendTo32(context, context.ShiftRightU32(src, Const(24)), 8), - VectorSelect.S16H0 => SignExtendTo32(context, context.ShiftRightU32(src, Const(0)), 16), - VectorSelect.S16H1 => SignExtendTo32(context, context.ShiftRightU32(src, Const(16)), 16), - _ => src - }; - } - - public static void SetZnFlags(EmitterContext context, Operand dest, bool setCC, bool extended = false) - { - if (!setCC) - { - return; - } - - if (extended) - { - // When the operation is extended, it means we are doing - // the operation on a long word with any number of bits, - // so we need to AND the zero flag from result with the - // previous result when extended is specified, to ensure - // we have ZF set only if all words are zero, and not just - // the last one. - Operand oldZF = GetZF(); - - Operand res = context.BitwiseAnd(context.ICompareEqual(dest, Const(0)), oldZF); - - context.Copy(GetZF(), res); - } - else - { - context.Copy(GetZF(), context.ICompareEqual(dest, Const(0))); - } - - context.Copy(GetNF(), context.ICompareLess(dest, Const(0))); - } - - public static void SetFPZnFlags(EmitterContext context, Operand dest, bool setCC, Instruction fpType = Instruction.FP32) - { - if (setCC) - { - Operand zero = ConstF(0); - - if (fpType == Instruction.FP64) - { - zero = context.FP32ConvertToFP64(zero); - } - - context.Copy(GetZF(), context.FPCompareEqual(dest, zero, fpType)); - context.Copy(GetNF(), context.FPCompareLess (dest, zero, fpType)); - } - } - - public static (Operand, Operand) NegateLong(EmitterContext context, Operand low, Operand high) - { - low = context.BitwiseNot(low); - high = context.BitwiseNot(high); - low = AddWithCarry(context, low, Const(1), out Operand carryOut); - high = context.IAdd(high, carryOut); - return (low, high); - } - - public static Operand AddWithCarry(EmitterContext context, Operand lhs, Operand rhs, out Operand carryOut) - { - Operand result = context.IAdd(lhs, rhs); - - // C = Rd < Rn - carryOut = context.INegate(context.ICompareLessUnsigned(result, lhs)); - - return result; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitAttribute.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitAttribute.cs deleted file mode 100644 index 1df38761..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitAttribute.cs +++ /dev/null @@ -1,383 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; - -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - public static void Al2p(EmitterContext context) - { - InstAl2p op = context.GetOp<InstAl2p>(); - - context.Copy(GetDest(op.Dest), context.IAdd(GetSrcReg(context, op.SrcA), Const(op.Imm11))); - } - - public static void Ald(EmitterContext context) - { - InstAld op = context.GetOp<InstAld>(); - - // Some of those attributes are per invocation, - // so we should ignore any primitive vertex indexing for those. - bool hasPrimitiveVertex = AttributeMap.HasPrimitiveVertex(context.Config.Stage, op.O) && !op.P; - - if (!op.Phys) - { - hasPrimitiveVertex &= HasPrimitiveVertex(op.Imm11); - } - - Operand primVertex = hasPrimitiveVertex ? context.Copy(GetSrcReg(context, op.SrcB)) : null; - - for (int index = 0; index < (int)op.AlSize + 1; index++) - { - Register rd = new Register(op.Dest + index, RegisterType.Gpr); - - if (rd.IsRZ) - { - break; - } - - if (op.Phys) - { - Operand offset = context.ISubtract(GetSrcReg(context, op.SrcA), Const(AttributeConsts.UserAttributeBase)); - Operand vecIndex = context.ShiftRightU32(offset, Const(4)); - Operand elemIndex = context.BitwiseAnd(context.ShiftRightU32(offset, Const(2)), Const(3)); - - StorageKind storageKind = op.O ? StorageKind.Output : StorageKind.Input; - - context.Copy(Register(rd), context.Load(storageKind, IoVariable.UserDefined, primVertex, vecIndex, elemIndex)); - } - else if (op.SrcB == RegisterConsts.RegisterZeroIndex || op.P) - { - int offset = FixedFuncToUserAttribute(context.Config, op.Imm11 + index * 4, op.O); - - context.FlagAttributeRead(offset); - - bool isOutput = op.O && CanLoadOutput(offset); - - if (!op.P && !isOutput && TryConvertIdToIndexForVulkan(context, offset, out Operand value)) - { - context.Copy(Register(rd), value); - } - else - { - context.Copy(Register(rd), AttributeMap.GenerateAttributeLoad(context, primVertex, offset, isOutput, op.P)); - } - } - else - { - int offset = FixedFuncToUserAttribute(context.Config, op.Imm11 + index * 4, op.O); - - context.FlagAttributeRead(offset); - - bool isOutput = op.O && CanLoadOutput(offset); - - context.Copy(Register(rd), AttributeMap.GenerateAttributeLoad(context, primVertex, offset, isOutput, false)); - } - } - } - - public static void Ast(EmitterContext context) - { - InstAst op = context.GetOp<InstAst>(); - - for (int index = 0; index < (int)op.AlSize + 1; index++) - { - if (op.SrcB + index > RegisterConsts.RegisterZeroIndex) - { - break; - } - - Register rd = new Register(op.SrcB + index, RegisterType.Gpr); - - if (op.Phys) - { - Operand offset = context.ISubtract(GetSrcReg(context, op.SrcA), Const(AttributeConsts.UserAttributeBase)); - Operand vecIndex = context.ShiftRightU32(offset, Const(4)); - Operand elemIndex = context.BitwiseAnd(context.ShiftRightU32(offset, Const(2)), Const(3)); - Operand invocationId = AttributeMap.HasInvocationId(context.Config.Stage, isOutput: true) - ? context.Load(StorageKind.Input, IoVariable.InvocationId) - : null; - - context.Store(StorageKind.Output, IoVariable.UserDefined, invocationId, vecIndex, elemIndex, Register(rd)); - } - else - { - // TODO: Support indirect stores using Ra. - - int offset = op.Imm11 + index * 4; - - if (!context.Config.IsUsedOutputAttribute(offset)) - { - return; - } - - offset = FixedFuncToUserAttribute(context.Config, offset, isOutput: true); - - context.FlagAttributeWritten(offset); - - AttributeMap.GenerateAttributeStore(context, offset, op.P, Register(rd)); - } - } - } - - public static void Ipa(EmitterContext context) - { - InstIpa op = context.GetOp<InstIpa>(); - - context.FlagAttributeRead(op.Imm10); - - Operand res; - - bool isFixedFunc = false; - - if (op.Idx) - { - Operand offset = context.ISubtract(GetSrcReg(context, op.SrcA), Const(AttributeConsts.UserAttributeBase)); - Operand vecIndex = context.ShiftRightU32(offset, Const(4)); - Operand elemIndex = context.BitwiseAnd(context.ShiftRightU32(offset, Const(2)), Const(3)); - - res = context.Load(StorageKind.Input, IoVariable.UserDefined, null, vecIndex, elemIndex); - res = context.FPMultiply(res, context.Load(StorageKind.Input, IoVariable.FragmentCoord, null, Const(3))); - } - else - { - isFixedFunc = TryFixedFuncToUserAttributeIpa(context, op.Imm10, out res); - - if (op.Imm10 >= AttributeConsts.UserAttributeBase && op.Imm10 < AttributeConsts.UserAttributeEnd) - { - int index = (op.Imm10 - AttributeConsts.UserAttributeBase) >> 4; - - if (context.Config.ImapTypes[index].GetFirstUsedType() == PixelImap.Perspective) - { - res = context.FPMultiply(res, context.Load(StorageKind.Input, IoVariable.FragmentCoord, null, Const(3))); - } - } - else if (op.Imm10 == AttributeConsts.PositionX || op.Imm10 == AttributeConsts.PositionY) - { - // FragCoord X/Y must be divided by the render target scale, if resolution scaling is active, - // because the shader code is not expecting scaled values. - res = context.FPDivide(res, context.Load(StorageKind.Input, IoVariable.SupportBlockRenderScale, null, Const(0))); - } - else if (op.Imm10 == AttributeConsts.FrontFacing && context.Config.GpuAccessor.QueryHostHasFrontFacingBug()) - { - // gl_FrontFacing sometimes has incorrect (flipped) values depending how it is accessed on Intel GPUs. - // This weird trick makes it behave. - res = context.ICompareLess(context.INegate(context.IConvertS32ToFP32(res)), Const(0)); - } - } - - if (op.IpaOp == IpaOp.Multiply && !isFixedFunc) - { - Operand srcB = GetSrcReg(context, op.SrcB); - - res = context.FPMultiply(res, srcB); - } - - res = context.FPSaturate(res, op.Sat); - - context.Copy(GetDest(op.Dest), res); - } - - public static void Isberd(EmitterContext context) - { - InstIsberd op = context.GetOp<InstIsberd>(); - - // This instruction performs a load from ISBE (Internal Stage Buffer Entry) memory. - // Here, we just propagate the offset, as the result from this instruction is usually - // used with ALD to perform vertex load on geometry or tessellation shaders. - // The offset is calculated as (PrimitiveIndex * VerticesPerPrimitive) + VertexIndex. - // Since we hardcode PrimitiveIndex to zero, then the offset will be just VertexIndex. - context.Copy(GetDest(op.Dest), GetSrcReg(context, op.SrcA)); - } - - public static void OutR(EmitterContext context) - { - InstOutR op = context.GetOp<InstOutR>(); - - EmitOut(context, op.OutType.HasFlag(OutType.Emit), op.OutType.HasFlag(OutType.Cut)); - } - - public static void OutI(EmitterContext context) - { - InstOutI op = context.GetOp<InstOutI>(); - - EmitOut(context, op.OutType.HasFlag(OutType.Emit), op.OutType.HasFlag(OutType.Cut)); - } - - public static void OutC(EmitterContext context) - { - InstOutC op = context.GetOp<InstOutC>(); - - EmitOut(context, op.OutType.HasFlag(OutType.Emit), op.OutType.HasFlag(OutType.Cut)); - } - - private static void EmitOut(EmitterContext context, bool emit, bool cut) - { - if (!(emit || cut)) - { - context.Config.GpuAccessor.Log("Invalid OUT encoding."); - } - - if (emit) - { - if (context.Config.LastInVertexPipeline) - { - context.PrepareForVertexReturn(out var tempXLocal, out var tempYLocal, out var tempZLocal); - - context.EmitVertex(); - - // Restore output position value before transformation. - - if (tempXLocal != null) - { - context.Copy(context.Load(StorageKind.Input, IoVariable.Position, null, Const(0)), tempXLocal); - } - - if (tempYLocal != null) - { - context.Copy(context.Load(StorageKind.Input, IoVariable.Position, null, Const(1)), tempYLocal); - } - - if (tempZLocal != null) - { - context.Copy(context.Load(StorageKind.Input, IoVariable.Position, null, Const(2)), tempZLocal); - } - } - else - { - context.EmitVertex(); - } - } - - if (cut) - { - context.EndPrimitive(); - } - } - - private static bool HasPrimitiveVertex(int attr) - { - return attr != AttributeConsts.PrimitiveId && - attr != AttributeConsts.TessCoordX && - attr != AttributeConsts.TessCoordY; - } - - private static bool CanLoadOutput(int attr) - { - return attr != AttributeConsts.TessCoordX && attr != AttributeConsts.TessCoordY; - } - - private static bool TryFixedFuncToUserAttributeIpa(EmitterContext context, int attr, out Operand selectedAttr) - { - if (attr >= AttributeConsts.FrontColorDiffuseR && attr < AttributeConsts.BackColorDiffuseR) - { - // TODO: If two sided rendering is enabled, then this should return - // FrontColor if the fragment is front facing, and back color otherwise. - selectedAttr = GenerateIpaLoad(context, FixedFuncToUserAttribute(context.Config, attr, isOutput: false)); - return true; - } - else if (attr == AttributeConsts.FogCoord) - { - // TODO: We likely need to emulate the fixed-function functionality for FogCoord here. - selectedAttr = GenerateIpaLoad(context, FixedFuncToUserAttribute(context.Config, attr, isOutput: false)); - return true; - } - else if (attr >= AttributeConsts.BackColorDiffuseR && attr < AttributeConsts.ClipDistance0) - { - selectedAttr = ConstF(((attr >> 2) & 3) == 3 ? 1f : 0f); - return true; - } - else if (attr >= AttributeConsts.TexCoordBase && attr < AttributeConsts.TexCoordEnd) - { - selectedAttr = GenerateIpaLoad(context, FixedFuncToUserAttribute(context.Config, attr, isOutput: false)); - return true; - } - - selectedAttr = GenerateIpaLoad(context, attr); - return false; - } - - private static Operand GenerateIpaLoad(EmitterContext context, int offset) - { - return AttributeMap.GenerateAttributeLoad(context, null, offset, isOutput: false, isPerPatch: false); - } - - private static int FixedFuncToUserAttribute(ShaderConfig config, int attr, bool isOutput) - { - bool supportsLayerFromVertexOrTess = config.GpuAccessor.QueryHostSupportsLayerVertexTessellation(); - int fixedStartAttr = supportsLayerFromVertexOrTess ? 0 : 1; - - if (attr == AttributeConsts.Layer && config.Stage != ShaderStage.Geometry && !supportsLayerFromVertexOrTess) - { - attr = FixedFuncToUserAttribute(config, attr, AttributeConsts.Layer, 0, isOutput); - config.SetLayerOutputAttribute(attr); - } - else if (attr == AttributeConsts.FogCoord) - { - attr = FixedFuncToUserAttribute(config, attr, AttributeConsts.FogCoord, fixedStartAttr, isOutput); - } - else if (attr >= AttributeConsts.FrontColorDiffuseR && attr < AttributeConsts.ClipDistance0) - { - attr = FixedFuncToUserAttribute(config, attr, AttributeConsts.FrontColorDiffuseR, fixedStartAttr + 1, isOutput); - } - else if (attr >= AttributeConsts.TexCoordBase && attr < AttributeConsts.TexCoordEnd) - { - attr = FixedFuncToUserAttribute(config, attr, AttributeConsts.TexCoordBase, fixedStartAttr + 5, isOutput); - } - - return attr; - } - - private static int FixedFuncToUserAttribute(ShaderConfig config, int attr, int baseAttr, int baseIndex, bool isOutput) - { - int index = (attr - baseAttr) >> 4; - int userAttrIndex = config.GetFreeUserAttribute(isOutput, baseIndex + index); - - if ((uint)userAttrIndex < Constants.MaxAttributes) - { - attr = AttributeConsts.UserAttributeBase + userAttrIndex * 16 + (attr & 0xf); - - if (isOutput) - { - config.SetOutputUserAttributeFixedFunc(userAttrIndex); - } - else - { - config.SetInputUserAttributeFixedFunc(userAttrIndex); - } - } - else - { - config.GpuAccessor.Log($"No enough user attributes for fixed attribute offset 0x{attr:X}."); - } - - return attr; - } - - private static bool TryConvertIdToIndexForVulkan(EmitterContext context, int attr, out Operand value) - { - if (context.Config.Options.TargetApi == TargetApi.Vulkan) - { - if (attr == AttributeConsts.InstanceId) - { - value = context.ISubtract( - context.Load(StorageKind.Input, IoVariable.InstanceIndex), - context.Load(StorageKind.Input, IoVariable.BaseInstance)); - return true; - } - else if (attr == AttributeConsts.VertexId) - { - value = context.Load(StorageKind.Input, IoVariable.VertexIndex); - return true; - } - } - - value = null; - return false; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitBarrier.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitBarrier.cs deleted file mode 100644 index f3114c6e..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitBarrier.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.Translation; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - public static void Bar(EmitterContext context) - { - InstBar op = context.GetOp<InstBar>(); - - // TODO: Support other modes. - if (op.BarOp == BarOp.Sync) - { - context.Barrier(); - } - else - { - context.Config.GpuAccessor.Log($"Invalid barrier mode: {op.BarOp}."); - } - } - - public static void Depbar(EmitterContext context) - { - InstDepbar op = context.GetOp<InstDepbar>(); - - // No operation. - } - - public static void Membar(EmitterContext context) - { - InstMembar op = context.GetOp<InstMembar>(); - - if (op.Membar == Decoders.Membar.Cta) - { - context.GroupMemoryBarrier(); - } - else - { - context.MemoryBarrier(); - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitBitfield.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitBitfield.cs deleted file mode 100644 index 71925269..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitBitfield.cs +++ /dev/null @@ -1,194 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; - -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - public static void BfeR(EmitterContext context) - { - InstBfeR op = context.GetOp<InstBfeR>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcB); - - EmitBfe(context, srcA, srcB, op.Dest, op.Brev, op.Signed); - } - - public static void BfeI(EmitterContext context) - { - InstBfeI op = context.GetOp<InstBfeI>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); - - EmitBfe(context, srcA, srcB, op.Dest, op.Brev, op.Signed); - } - - public static void BfeC(EmitterContext context) - { - InstBfeC op = context.GetOp<InstBfeC>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - - EmitBfe(context, srcA, srcB, op.Dest, op.Brev, op.Signed); - } - - public static void BfiR(EmitterContext context) - { - InstBfiR op = context.GetOp<InstBfiR>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcB); - var srcC = GetSrcReg(context, op.SrcC); - - EmitBfi(context, srcA, srcB, srcC, op.Dest); - } - - public static void BfiI(EmitterContext context) - { - InstBfiI op = context.GetOp<InstBfiI>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); - var srcC = GetSrcReg(context, op.SrcC); - - EmitBfi(context, srcA, srcB, srcC, op.Dest); - } - - public static void BfiC(EmitterContext context) - { - InstBfiC op = context.GetOp<InstBfiC>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - var srcC = GetSrcReg(context, op.SrcC); - - EmitBfi(context, srcA, srcB, srcC, op.Dest); - } - - public static void BfiRc(EmitterContext context) - { - InstBfiRc op = context.GetOp<InstBfiRc>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcC); - var srcC = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - - EmitBfi(context, srcA, srcB, srcC, op.Dest); - } - - public static void FloR(EmitterContext context) - { - InstFloR op = context.GetOp<InstFloR>(); - - EmitFlo(context, GetSrcReg(context, op.SrcB), op.Dest, op.NegB, op.Sh, op.Signed); - } - - public static void FloI(EmitterContext context) - { - InstFloI op = context.GetOp<InstFloI>(); - - EmitFlo(context, GetSrcImm(context, Imm20ToSInt(op.Imm20)), op.Dest, op.NegB, op.Sh, op.Signed); - } - - public static void FloC(EmitterContext context) - { - InstFloC op = context.GetOp<InstFloC>(); - - EmitFlo(context, GetSrcCbuf(context, op.CbufSlot, op.CbufOffset), op.Dest, op.NegB, op.Sh, op.Signed); - } - - public static void PopcR(EmitterContext context) - { - InstPopcR op = context.GetOp<InstPopcR>(); - - EmitPopc(context, GetSrcReg(context, op.SrcB), op.Dest, op.NegB); - } - - public static void PopcI(EmitterContext context) - { - InstPopcI op = context.GetOp<InstPopcI>(); - - EmitPopc(context, GetSrcImm(context, Imm20ToSInt(op.Imm20)), op.Dest, op.NegB); - } - - public static void PopcC(EmitterContext context) - { - InstPopcC op = context.GetOp<InstPopcC>(); - - EmitPopc(context, GetSrcCbuf(context, op.CbufSlot, op.CbufOffset), op.Dest, op.NegB); - } - - private static void EmitBfe( - EmitterContext context, - Operand srcA, - Operand srcB, - int rd, - bool bitReverse, - bool isSigned) - { - if (bitReverse) - { - srcA = context.BitfieldReverse(srcA); - } - - Operand position = context.BitwiseAnd(srcB, Const(0xff)); - - Operand size = context.BitfieldExtractU32(srcB, Const(8), Const(8)); - - Operand res = isSigned - ? context.BitfieldExtractS32(srcA, position, size) - : context.BitfieldExtractU32(srcA, position, size); - - context.Copy(GetDest(rd), res); - - // TODO: CC, X, corner cases. - } - - private static void EmitBfi(EmitterContext context, Operand srcA, Operand srcB, Operand srcC, int rd) - { - Operand position = context.BitwiseAnd(srcB, Const(0xff)); - - Operand size = context.BitfieldExtractU32(srcB, Const(8), Const(8)); - - Operand res = context.BitfieldInsert(srcC, srcA, position, size); - - context.Copy(GetDest(rd), res); - } - - private static void EmitFlo(EmitterContext context, Operand src, int rd, bool invert, bool sh, bool isSigned) - { - Operand srcB = context.BitwiseNot(src, invert); - - Operand res; - - if (sh) - { - res = context.FindLSB(context.BitfieldReverse(srcB)); - } - else - { - res = isSigned - ? context.FindMSBS32(srcB) - : context.FindMSBU32(srcB); - } - - context.Copy(GetDest(rd), res); - } - - private static void EmitPopc(EmitterContext context, Operand src, int rd, bool invert) - { - Operand srcB = context.BitwiseNot(src, invert); - - Operand res = context.BitCount(srcB); - - context.Copy(GetDest(rd), res); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitConditionCode.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitConditionCode.cs deleted file mode 100644 index 74ac7602..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitConditionCode.cs +++ /dev/null @@ -1,87 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; - -using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - public static void Cset(EmitterContext context) - { - InstCset op = context.GetOp<InstCset>(); - - Operand res = GetCondition(context, op.Ccc); - Operand srcPred = GetPredicate(context, op.SrcPred, op.SrcPredInv); - - res = GetPredLogicalOp(context, op.Bop, res, srcPred); - - Operand dest = GetDest(op.Dest); - - if (op.BVal) - { - context.Copy(dest, context.ConditionalSelect(res, ConstF(1), Const(0))); - } - else - { - context.Copy(dest, res); - } - - // TODO: CC. - } - - public static void Csetp(EmitterContext context) - { - InstCsetp op = context.GetOp<InstCsetp>(); - - Operand p0Res = GetCondition(context, op.Ccc); - Operand p1Res = context.BitwiseNot(p0Res); - Operand srcPred = GetPredicate(context, op.SrcPred, op.SrcPredInv); - - p0Res = GetPredLogicalOp(context, op.Bop, p0Res, srcPred); - p1Res = GetPredLogicalOp(context, op.Bop, p1Res, srcPred); - - context.Copy(Register(op.DestPred, RegisterType.Predicate), p0Res); - context.Copy(Register(op.DestPredInv, RegisterType.Predicate), p1Res); - - // TODO: CC. - } - - private static Operand GetCondition(EmitterContext context, Ccc cond, int defaultCond = IrConsts.True) - { - return cond switch - { - Ccc.F => Const(IrConsts.False), - Ccc.Lt => context.BitwiseExclusiveOr(context.BitwiseAnd(GetNF(), context.BitwiseNot(GetZF())), GetVF()), - Ccc.Eq => context.BitwiseAnd(context.BitwiseNot(GetNF()), GetZF()), - Ccc.Le => context.BitwiseExclusiveOr(GetNF(), context.BitwiseOr(GetZF(), GetVF())), - Ccc.Gt => context.BitwiseNot(context.BitwiseOr(context.BitwiseExclusiveOr(GetNF(), GetVF()), GetZF())), - Ccc.Ne => context.BitwiseNot(GetZF()), - Ccc.Ge => context.BitwiseNot(context.BitwiseExclusiveOr(GetNF(), GetVF())), - Ccc.Num => context.BitwiseNot(context.BitwiseAnd(GetNF(), GetZF())), - Ccc.Nan => context.BitwiseAnd(GetNF(), GetZF()), - Ccc.Ltu => context.BitwiseExclusiveOr(GetNF(), GetVF()), - Ccc.Equ => GetZF(), - Ccc.Leu => context.BitwiseOr(context.BitwiseExclusiveOr(GetNF(), GetVF()), GetZF()), - Ccc.Gtu => context.BitwiseExclusiveOr(context.BitwiseNot(GetNF()), context.BitwiseOr(GetVF(), GetZF())), - Ccc.Neu => context.BitwiseOr(GetNF(), context.BitwiseNot(GetZF())), - Ccc.Geu => context.BitwiseExclusiveOr(context.BitwiseOr(context.BitwiseNot(GetNF()), GetZF()), GetVF()), - Ccc.T => Const(IrConsts.True), - Ccc.Off => context.BitwiseNot(GetVF()), - Ccc.Lo => context.BitwiseNot(GetCF()), - Ccc.Sff => context.BitwiseNot(GetNF()), - Ccc.Ls => context.BitwiseOr(GetZF(), context.BitwiseNot(GetCF())), - Ccc.Hi => context.BitwiseAnd(GetCF(), context.BitwiseNot(GetZF())), - Ccc.Sft => GetNF(), - Ccc.Hs => GetCF(), - Ccc.Oft => GetVF(), - Ccc.Rle => context.BitwiseOr(GetNF(), GetZF()), - Ccc.Rgt => context.BitwiseNot(context.BitwiseOr(GetNF(), GetZF())), - _ => Const(defaultCond) - }; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs deleted file mode 100644 index bebd96dd..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs +++ /dev/null @@ -1,425 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; -using System; - -using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - public static void F2fR(EmitterContext context) - { - InstF2fR op = context.GetOp<InstF2fR>(); - - var src = UnpackReg(context, op.SrcFmt, op.Sh, op.SrcB); - - EmitF2F(context, op.SrcFmt, op.DstFmt, op.RoundMode, src, op.Dest, op.AbsB, op.NegB, op.Sat); - } - - public static void F2fI(EmitterContext context) - { - InstF2fI op = context.GetOp<InstF2fI>(); - - var src = UnpackImm(context, op.SrcFmt, op.Sh, Imm20ToFloat(op.Imm20)); - - EmitF2F(context, op.SrcFmt, op.DstFmt, op.RoundMode, src, op.Dest, op.AbsB, op.NegB, op.Sat); - } - - public static void F2fC(EmitterContext context) - { - InstF2fC op = context.GetOp<InstF2fC>(); - - var src = UnpackCbuf(context, op.SrcFmt, op.Sh, op.CbufSlot, op.CbufOffset); - - EmitF2F(context, op.SrcFmt, op.DstFmt, op.RoundMode, src, op.Dest, op.AbsB, op.NegB, op.Sat); - } - - public static void F2iR(EmitterContext context) - { - InstF2iR op = context.GetOp<InstF2iR>(); - - var src = UnpackReg(context, op.SrcFmt, op.Sh, op.SrcB); - - EmitF2I(context, op.SrcFmt, op.IDstFmt, op.RoundMode, src, op.Dest, op.AbsB, op.NegB); - } - - public static void F2iI(EmitterContext context) - { - InstF2iI op = context.GetOp<InstF2iI>(); - - var src = UnpackImm(context, op.SrcFmt, op.Sh, Imm20ToFloat(op.Imm20)); - - EmitF2I(context, op.SrcFmt, op.IDstFmt, op.RoundMode, src, op.Dest, op.AbsB, op.NegB); - } - - public static void F2iC(EmitterContext context) - { - InstF2iC op = context.GetOp<InstF2iC>(); - - var src = UnpackCbuf(context, op.SrcFmt, op.Sh, op.CbufSlot, op.CbufOffset); - - EmitF2I(context, op.SrcFmt, op.IDstFmt, op.RoundMode, src, op.Dest, op.AbsB, op.NegB); - } - - public static void I2fR(EmitterContext context) - { - InstI2fR op = context.GetOp<InstI2fR>(); - - var src = GetSrcReg(context, op.SrcB); - - EmitI2F(context, op.ISrcFmt, op.DstFmt, src, op.ByteSel, op.Dest, op.AbsB, op.NegB); - } - - public static void I2fI(EmitterContext context) - { - InstI2fI op = context.GetOp<InstI2fI>(); - - var src = GetSrcImm(context, Imm20ToSInt(op.Imm20)); - - EmitI2F(context, op.ISrcFmt, op.DstFmt, src, op.ByteSel, op.Dest, op.AbsB, op.NegB); - } - - public static void I2fC(EmitterContext context) - { - InstI2fC op = context.GetOp<InstI2fC>(); - - var src = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - - EmitI2F(context, op.ISrcFmt, op.DstFmt, src, op.ByteSel, op.Dest, op.AbsB, op.NegB); - } - - public static void I2iR(EmitterContext context) - { - InstI2iR op = context.GetOp<InstI2iR>(); - - var src = GetSrcReg(context, op.SrcB); - - EmitI2I(context, op.ISrcFmt, op.IDstFmt, src, op.ByteSel, op.Dest, op.AbsB, op.NegB, op.Sat, op.WriteCC); - } - - public static void I2iI(EmitterContext context) - { - InstI2iI op = context.GetOp<InstI2iI>(); - - var src = GetSrcImm(context, Imm20ToSInt(op.Imm20)); - - EmitI2I(context, op.ISrcFmt, op.IDstFmt, src, op.ByteSel, op.Dest, op.AbsB, op.NegB, op.Sat, op.WriteCC); - } - - public static void I2iC(EmitterContext context) - { - InstI2iC op = context.GetOp<InstI2iC>(); - - var src = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - - EmitI2I(context, op.ISrcFmt, op.IDstFmt, src, op.ByteSel, op.Dest, op.AbsB, op.NegB, op.Sat, op.WriteCC); - } - - private static void EmitF2F( - EmitterContext context, - DstFmt srcType, - DstFmt dstType, - IntegerRound roundingMode, - Operand src, - int rd, - bool absolute, - bool negate, - bool saturate) - { - Operand srcB = context.FPAbsNeg(src, absolute, negate, srcType.ToInstFPType()); - - if (srcType == dstType) - { - srcB = roundingMode switch - { - IntegerRound.Round => context.FPRound(srcB, srcType.ToInstFPType()), - IntegerRound.Floor => context.FPFloor(srcB, srcType.ToInstFPType()), - IntegerRound.Ceil => context.FPCeiling(srcB, srcType.ToInstFPType()), - IntegerRound.Trunc => context.FPTruncate(srcB, srcType.ToInstFPType()), - _ => srcB - }; - } - - // We don't need to handle conversions between FP16 <-> FP32 - // since we do FP16 operations as FP32 directly. - // FP16 <-> FP64 conversions are invalid. - if (srcType == DstFmt.F32 && dstType == DstFmt.F64) - { - srcB = context.FP32ConvertToFP64(srcB); - } - else if (srcType == DstFmt.F64 && dstType == DstFmt.F32) - { - srcB = context.FP64ConvertToFP32(srcB); - } - - srcB = context.FPSaturate(srcB, saturate, dstType.ToInstFPType()); - - WriteFP(context, dstType, srcB, rd); - - // TODO: CC. - } - - private static void EmitF2I( - EmitterContext context, - DstFmt srcType, - IDstFmt dstType, - RoundMode2 roundingMode, - Operand src, - int rd, - bool absolute, - bool negate) - { - if (dstType == IDstFmt.U64) - { - context.Config.GpuAccessor.Log("Unimplemented 64-bits F2I."); - } - - Instruction fpType = srcType.ToInstFPType(); - - bool isSignedInt = dstType == IDstFmt.S16 || dstType == IDstFmt.S32 || dstType == IDstFmt.S64; - bool isSmallInt = dstType == IDstFmt.U16 || dstType == IDstFmt.S16; - - Operand srcB = context.FPAbsNeg(src, absolute, negate, fpType); - - srcB = roundingMode switch - { - RoundMode2.Round => context.FPRound(srcB, fpType), - RoundMode2.Floor => context.FPFloor(srcB, fpType), - RoundMode2.Ceil => context.FPCeiling(srcB, fpType), - RoundMode2.Trunc => context.FPTruncate(srcB, fpType), - _ => srcB - }; - - if (!isSignedInt) - { - // Negative float to uint cast is undefined, so we clamp the value before conversion. - Operand c0 = srcType == DstFmt.F64 ? context.PackDouble2x32(0.0) : ConstF(0); - - srcB = context.FPMaximum(srcB, c0, fpType); - } - - if (srcType == DstFmt.F64) - { - srcB = isSignedInt - ? context.FP64ConvertToS32(srcB) - : context.FP64ConvertToU32(srcB); - } - else - { - srcB = isSignedInt - ? context.FP32ConvertToS32(srcB) - : context.FP32ConvertToU32(srcB); - } - - if (isSmallInt) - { - int min = (int)GetIntMin(dstType); - int max = (int)GetIntMax(dstType); - - srcB = isSignedInt - ? context.IClampS32(srcB, Const(min), Const(max)) - : context.IClampU32(srcB, Const(min), Const(max)); - } - - Operand dest = GetDest(rd); - - context.Copy(dest, srcB); - - // TODO: CC. - } - - private static void EmitI2F( - EmitterContext context, - ISrcFmt srcType, - DstFmt dstType, - Operand src, - ByteSel byteSelection, - int rd, - bool absolute, - bool negate) - { - bool isSignedInt = - srcType == ISrcFmt.S8 || - srcType == ISrcFmt.S16 || - srcType == ISrcFmt.S32 || - srcType == ISrcFmt.S64; - bool isSmallInt = - srcType == ISrcFmt.U16 || - srcType == ISrcFmt.S16 || - srcType == ISrcFmt.U8 || - srcType == ISrcFmt.S8; - - // TODO: Handle S/U64. - - Operand srcB = context.IAbsNeg(src, absolute, negate); - - if (isSmallInt) - { - int size = srcType == ISrcFmt.U16 || srcType == ISrcFmt.S16 ? 16 : 8; - - srcB = isSignedInt - ? context.BitfieldExtractS32(srcB, Const((int)byteSelection * 8), Const(size)) - : context.BitfieldExtractU32(srcB, Const((int)byteSelection * 8), Const(size)); - } - - if (dstType == DstFmt.F64) - { - srcB = isSignedInt - ? context.IConvertS32ToFP64(srcB) - : context.IConvertU32ToFP64(srcB); - } - else - { - srcB = isSignedInt - ? context.IConvertS32ToFP32(srcB) - : context.IConvertU32ToFP32(srcB); - } - - WriteFP(context, dstType, srcB, rd); - - // TODO: CC. - } - - private static void EmitI2I( - EmitterContext context, - ISrcDstFmt srcType, - ISrcDstFmt dstType, - Operand src, - ByteSel byteSelection, - int rd, - bool absolute, - bool negate, - bool saturate, - bool writeCC) - { - if ((srcType & ~ISrcDstFmt.S8) > ISrcDstFmt.U32 || (dstType & ~ISrcDstFmt.S8) > ISrcDstFmt.U32) - { - context.Config.GpuAccessor.Log("Invalid I2I encoding."); - return; - } - - bool srcIsSignedInt = - srcType == ISrcDstFmt.S8 || - srcType == ISrcDstFmt.S16 || - srcType == ISrcDstFmt.S32; - bool dstIsSignedInt = - dstType == ISrcDstFmt.S8 || - dstType == ISrcDstFmt.S16 || - dstType == ISrcDstFmt.S32; - bool srcIsSmallInt = - srcType == ISrcDstFmt.U16 || - srcType == ISrcDstFmt.S16 || - srcType == ISrcDstFmt.U8 || - srcType == ISrcDstFmt.S8; - - if (srcIsSmallInt) - { - int size = srcType == ISrcDstFmt.U16 || srcType == ISrcDstFmt.S16 ? 16 : 8; - - src = srcIsSignedInt - ? context.BitfieldExtractS32(src, Const((int)byteSelection * 8), Const(size)) - : context.BitfieldExtractU32(src, Const((int)byteSelection * 8), Const(size)); - } - - src = context.IAbsNeg(src, absolute, negate); - - if (saturate) - { - int min = (int)GetIntMin(dstType); - int max = (int)GetIntMax(dstType); - - src = dstIsSignedInt - ? context.IClampS32(src, Const(min), Const(max)) - : context.IClampU32(src, Const(min), Const(max)); - } - - context.Copy(GetDest(rd), src); - - SetZnFlags(context, src, writeCC); - } - - private static Operand UnpackReg(EmitterContext context, DstFmt floatType, bool h, int reg) - { - if (floatType == DstFmt.F32) - { - return GetSrcReg(context, reg); - } - else if (floatType == DstFmt.F16) - { - return GetHalfUnpacked(context, GetSrcReg(context, reg), HalfSwizzle.F16)[h ? 1 : 0]; - } - else if (floatType == DstFmt.F64) - { - return GetSrcReg(context, reg, isFP64: true); - } - - throw new ArgumentException($"Invalid floating point type \"{floatType}\"."); - } - - private static Operand UnpackCbuf(EmitterContext context, DstFmt floatType, bool h, int cbufSlot, int cbufOffset) - { - if (floatType == DstFmt.F32) - { - return GetSrcCbuf(context, cbufSlot, cbufOffset); - } - else if (floatType == DstFmt.F16) - { - return GetHalfUnpacked(context, GetSrcCbuf(context, cbufSlot, cbufOffset), HalfSwizzle.F16)[h ? 1 : 0]; - } - else if (floatType == DstFmt.F64) - { - return GetSrcCbuf(context, cbufSlot, cbufOffset, isFP64: true); - } - - throw new ArgumentException($"Invalid floating point type \"{floatType}\"."); - } - - private static Operand UnpackImm(EmitterContext context, DstFmt floatType, bool h, int imm) - { - if (floatType == DstFmt.F32) - { - return GetSrcImm(context, imm); - } - else if (floatType == DstFmt.F16) - { - return GetHalfUnpacked(context, GetSrcImm(context, imm), HalfSwizzle.F16)[h ? 1 : 0]; - } - else if (floatType == DstFmt.F64) - { - return GetSrcImm(context, imm, isFP64: true); - } - - throw new ArgumentException($"Invalid floating point type \"{floatType}\"."); - } - - private static void WriteFP(EmitterContext context, DstFmt type, Operand srcB, int rd) - { - Operand dest = GetDest(rd); - - if (type == DstFmt.F32) - { - context.Copy(dest, srcB); - } - else if (type == DstFmt.F16) - { - context.Copy(dest, context.PackHalf2x16(srcB, ConstF(0))); - } - else /* if (type == FPType.FP64) */ - { - Operand dest2 = GetDest2(rd); - - context.Copy(dest, context.UnpackDouble2x32Low(srcB)); - context.Copy(dest2, context.UnpackDouble2x32High(srcB)); - } - } - - private static Instruction ToInstFPType(this DstFmt type) - { - return type == DstFmt.F64 ? Instruction.FP64 : Instruction.FP32; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitFloatArithmetic.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitFloatArithmetic.cs deleted file mode 100644 index 29803c31..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitFloatArithmetic.cs +++ /dev/null @@ -1,532 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; - -using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - public static void DaddR(EmitterContext context) - { - InstDaddR op = context.GetOp<InstDaddR>(); - - var srcA = GetSrcReg(context, op.SrcA, isFP64: true); - var srcB = GetSrcReg(context, op.SrcB, isFP64: true); - - EmitFadd(context, Instruction.FP64, srcA, srcB, op.Dest, op.NegA, op.NegB, op.AbsA, op.AbsB, false, op.WriteCC); - } - - public static void DaddI(EmitterContext context) - { - InstDaddI op = context.GetOp<InstDaddI>(); - - var srcA = GetSrcReg(context, op.SrcA, isFP64: true); - var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20), isFP64: true); - - EmitFadd(context, Instruction.FP64, srcA, srcB, op.Dest, op.NegA, op.NegB, op.AbsA, op.AbsB, false, op.WriteCC); - } - - public static void DaddC(EmitterContext context) - { - InstDaddC op = context.GetOp<InstDaddC>(); - - var srcA = GetSrcReg(context, op.SrcA, isFP64: true); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset, isFP64: true); - - EmitFadd(context, Instruction.FP64, srcA, srcB, op.Dest, op.NegA, op.NegB, op.AbsA, op.AbsB, false, op.WriteCC); - } - - public static void DfmaR(EmitterContext context) - { - InstDfmaR op = context.GetOp<InstDfmaR>(); - - var srcA = GetSrcReg(context, op.SrcA, isFP64: true); - var srcB = GetSrcReg(context, op.SrcB, isFP64: true); - var srcC = GetSrcReg(context, op.SrcC, isFP64: true); - - EmitFfma(context, Instruction.FP64, srcA, srcB, srcC, op.Dest, op.NegA, op.NegC, false, op.WriteCC); - } - - public static void DfmaI(EmitterContext context) - { - InstDfmaI op = context.GetOp<InstDfmaI>(); - - var srcA = GetSrcReg(context, op.SrcA, isFP64: true); - var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20), isFP64: true); - var srcC = GetSrcReg(context, op.SrcC, isFP64: true); - - EmitFfma(context, Instruction.FP64, srcA, srcB, srcC, op.Dest, op.NegA, op.NegC, false, op.WriteCC); - } - - public static void DfmaC(EmitterContext context) - { - InstDfmaC op = context.GetOp<InstDfmaC>(); - - var srcA = GetSrcReg(context, op.SrcA, isFP64: true); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset, isFP64: true); - var srcC = GetSrcReg(context, op.SrcC, isFP64: true); - - EmitFfma(context, Instruction.FP64, srcA, srcB, srcC, op.Dest, op.NegA, op.NegC, false, op.WriteCC); - } - - public static void DfmaRc(EmitterContext context) - { - InstDfmaRc op = context.GetOp<InstDfmaRc>(); - - var srcA = GetSrcReg(context, op.SrcA, isFP64: true); - var srcB = GetSrcReg(context, op.SrcC, isFP64: true); - var srcC = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset, isFP64: true); - - EmitFfma(context, Instruction.FP64, srcA, srcB, srcC, op.Dest, op.NegA, op.NegC, false, op.WriteCC); - } - - public static void DmulR(EmitterContext context) - { - InstDmulR op = context.GetOp<InstDmulR>(); - - var srcA = GetSrcReg(context, op.SrcA, isFP64: true); - var srcB = GetSrcReg(context, op.SrcB, isFP64: true); - - EmitFmul(context, Instruction.FP64, MultiplyScale.NoScale, srcA, srcB, op.Dest, op.NegA, false, op.WriteCC); - } - - public static void DmulI(EmitterContext context) - { - InstDmulI op = context.GetOp<InstDmulI>(); - - var srcA = GetSrcReg(context, op.SrcA, isFP64: true); - var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20), isFP64: true); - - EmitFmul(context, Instruction.FP64, MultiplyScale.NoScale, srcA, srcB, op.Dest, op.NegA, false, op.WriteCC); - } - - public static void DmulC(EmitterContext context) - { - InstDmulC op = context.GetOp<InstDmulC>(); - - var srcA = GetSrcReg(context, op.SrcA, isFP64: true); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset, isFP64: true); - - EmitFmul(context, Instruction.FP64, MultiplyScale.NoScale, srcA, srcB, op.Dest, op.NegA, false, op.WriteCC); - } - - public static void FaddR(EmitterContext context) - { - InstFaddR op = context.GetOp<InstFaddR>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcB); - - EmitFadd(context, Instruction.FP32, srcA, srcB, op.Dest, op.NegA, op.NegB, op.AbsA, op.AbsB, op.Sat, op.WriteCC); - } - - public static void FaddI(EmitterContext context) - { - InstFaddI op = context.GetOp<InstFaddI>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20)); - - EmitFadd(context, Instruction.FP32, srcA, srcB, op.Dest, op.NegA, op.NegB, op.AbsA, op.AbsB, op.Sat, op.WriteCC); - } - - public static void FaddC(EmitterContext context) - { - InstFaddC op = context.GetOp<InstFaddC>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - - EmitFadd(context, Instruction.FP32, srcA, srcB, op.Dest, op.NegA, op.NegB, op.AbsA, op.AbsB, op.Sat, op.WriteCC); - } - - public static void Fadd32i(EmitterContext context) - { - InstFadd32i op = context.GetOp<InstFadd32i>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, op.Imm32); - - EmitFadd(context, Instruction.FP32, srcA, srcB, op.Dest, op.NegA, op.NegB, op.AbsA, op.AbsB, false, op.WriteCC); - } - - public static void FfmaR(EmitterContext context) - { - InstFfmaR op = context.GetOp<InstFfmaR>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcB); - var srcC = GetSrcReg(context, op.SrcC); - - EmitFfma(context, Instruction.FP32, srcA, srcB, srcC, op.Dest, op.NegA, op.NegC, op.Sat, op.WriteCC); - } - - public static void FfmaI(EmitterContext context) - { - InstFfmaI op = context.GetOp<InstFfmaI>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20)); - var srcC = GetSrcReg(context, op.SrcC); - - EmitFfma(context, Instruction.FP32, srcA, srcB, srcC, op.Dest, op.NegA, op.NegC, op.Sat, op.WriteCC); - } - - public static void FfmaC(EmitterContext context) - { - InstFfmaC op = context.GetOp<InstFfmaC>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - var srcC = GetSrcReg(context, op.SrcC); - - EmitFfma(context, Instruction.FP32, srcA, srcB, srcC, op.Dest, op.NegA, op.NegC, op.Sat, op.WriteCC); - } - - public static void FfmaRc(EmitterContext context) - { - InstFfmaRc op = context.GetOp<InstFfmaRc>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcC); - var srcC = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - - EmitFfma(context, Instruction.FP32, srcA, srcB, srcC, op.Dest, op.NegA, op.NegC, op.Sat, op.WriteCC); - } - - public static void Ffma32i(EmitterContext context) - { - InstFfma32i op = context.GetOp<InstFfma32i>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, op.Imm32); - var srcC = GetSrcReg(context, op.Dest); - - EmitFfma(context, Instruction.FP32, srcA, srcB, srcC, op.Dest, op.NegA, op.NegC, op.Sat, op.WriteCC); - } - - public static void FmulR(EmitterContext context) - { - InstFmulR op = context.GetOp<InstFmulR>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcB); - - EmitFmul(context, Instruction.FP32, op.Scale, srcA, srcB, op.Dest, op.NegA, op.Sat, op.WriteCC); - } - - public static void FmulI(EmitterContext context) - { - InstFmulI op = context.GetOp<InstFmulI>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20)); - - EmitFmul(context, Instruction.FP32, op.Scale, srcA, srcB, op.Dest, op.NegA, op.Sat, op.WriteCC); - } - - public static void FmulC(EmitterContext context) - { - InstFmulC op = context.GetOp<InstFmulC>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - - EmitFmul(context, Instruction.FP32, op.Scale, srcA, srcB, op.Dest, op.NegA, op.Sat, op.WriteCC); - } - - public static void Fmul32i(EmitterContext context) - { - InstFmul32i op = context.GetOp<InstFmul32i>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, op.Imm32); - - EmitFmul(context, Instruction.FP32, MultiplyScale.NoScale, srcA, srcB, op.Dest, false, op.Sat, op.WriteCC); - } - - public static void Hadd2R(EmitterContext context) - { - InstHadd2R op = context.GetOp<InstHadd2R>(); - - var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, op.AbsA); - var srcB = GetHalfSrc(context, op.BSwizzle, op.SrcB, op.NegB, op.AbsB); - - EmitHadd2Hmul2(context, op.OFmt, srcA, srcB, isAdd: true, op.Dest, op.Sat); - } - - public static void Hadd2I(EmitterContext context) - { - InstHadd2I op = context.GetOp<InstHadd2I>(); - - var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, op.AbsA); - var srcB = GetHalfSrc(context, op.BimmH0, op.BimmH1); - - EmitHadd2Hmul2(context, op.OFmt, srcA, srcB, isAdd: true, op.Dest, op.Sat); - } - - public static void Hadd2C(EmitterContext context) - { - InstHadd2C op = context.GetOp<InstHadd2C>(); - - var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, op.AbsA); - var srcB = GetHalfSrc(context, HalfSwizzle.F32, op.CbufSlot, op.CbufOffset, op.NegB, op.AbsB); - - EmitHadd2Hmul2(context, op.OFmt, srcA, srcB, isAdd: true, op.Dest, op.Sat); - } - - public static void Hadd232i(EmitterContext context) - { - InstHadd232i op = context.GetOp<InstHadd232i>(); - - var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, false); - var srcB = GetHalfSrc(context, op.Imm); - - EmitHadd2Hmul2(context, OFmt.F16, srcA, srcB, isAdd: true, op.Dest, op.Sat); - } - - public static void Hfma2R(EmitterContext context) - { - InstHfma2R op = context.GetOp<InstHfma2R>(); - - var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, false, false); - var srcB = GetHalfSrc(context, op.BSwizzle, op.SrcB, op.NegA, false); - var srcC = GetHalfSrc(context, op.CSwizzle, op.SrcC, op.NegC, false); - - EmitHfma2(context, op.OFmt, srcA, srcB, srcC, op.Dest, op.Sat); - } - - public static void Hfma2I(EmitterContext context) - { - InstHfma2I op = context.GetOp<InstHfma2I>(); - - var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, false, false); - var srcB = GetHalfSrc(context, op.BimmH0, op.BimmH1); - var srcC = GetHalfSrc(context, op.CSwizzle, op.SrcC, op.NegC, false); - - EmitHfma2(context, op.OFmt, srcA, srcB, srcC, op.Dest, op.Sat); - } - - public static void Hfma2C(EmitterContext context) - { - InstHfma2C op = context.GetOp<InstHfma2C>(); - - var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, false, false); - var srcB = GetHalfSrc(context, HalfSwizzle.F32, op.CbufSlot, op.CbufOffset, op.NegA, false); - var srcC = GetHalfSrc(context, op.CSwizzle, op.SrcC, op.NegC, false); - - EmitHfma2(context, op.OFmt, srcA, srcB, srcC, op.Dest, op.Sat); - } - - public static void Hfma2Rc(EmitterContext context) - { - InstHfma2Rc op = context.GetOp<InstHfma2Rc>(); - - var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, false, false); - var srcB = GetHalfSrc(context, op.CSwizzle, op.SrcC, op.NegA, false); - var srcC = GetHalfSrc(context, HalfSwizzle.F32, op.CbufSlot, op.CbufOffset, op.NegC, false); - - EmitHfma2(context, op.OFmt, srcA, srcB, srcC, op.Dest, op.Sat); - } - - public static void Hfma232i(EmitterContext context) - { - InstHfma232i op = context.GetOp<InstHfma232i>(); - - var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, false, false); - var srcB = GetHalfSrc(context, op.Imm); - var srcC = GetHalfSrc(context, HalfSwizzle.F16, op.Dest, op.NegC, false); - - EmitHfma2(context, OFmt.F16, srcA, srcB, srcC, op.Dest, saturate: false); - } - - public static void Hmul2R(EmitterContext context) - { - InstHmul2R op = context.GetOp<InstHmul2R>(); - - var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, false, op.AbsA); - var srcB = GetHalfSrc(context, op.BSwizzle, op.SrcB, op.NegA, op.AbsB); - - EmitHadd2Hmul2(context, op.OFmt, srcA, srcB, isAdd: false, op.Dest, op.Sat); - } - - public static void Hmul2I(EmitterContext context) - { - InstHmul2I op = context.GetOp<InstHmul2I>(); - - var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, op.AbsA); - var srcB = GetHalfSrc(context, op.BimmH0, op.BimmH1); - - EmitHadd2Hmul2(context, op.OFmt, srcA, srcB, isAdd: false, op.Dest, op.Sat); - } - - public static void Hmul2C(EmitterContext context) - { - InstHmul2C op = context.GetOp<InstHmul2C>(); - - var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, false, op.AbsA); - var srcB = GetHalfSrc(context, HalfSwizzle.F32, op.CbufSlot, op.CbufOffset, op.NegA, op.AbsB); - - EmitHadd2Hmul2(context, op.OFmt, srcA, srcB, isAdd: false, op.Dest, op.Sat); - } - - public static void Hmul232i(EmitterContext context) - { - InstHmul232i op = context.GetOp<InstHmul232i>(); - - var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, false, false); - var srcB = GetHalfSrc(context, op.Imm32); - - EmitHadd2Hmul2(context, OFmt.F16, srcA, srcB, isAdd: false, op.Dest, op.Sat); - } - - private static void EmitFadd( - EmitterContext context, - Instruction fpType, - Operand srcA, - Operand srcB, - int rd, - bool negateA, - bool negateB, - bool absoluteA, - bool absoluteB, - bool saturate, - bool writeCC) - { - bool isFP64 = fpType == Instruction.FP64; - - srcA = context.FPAbsNeg(srcA, absoluteA, negateA, fpType); - srcB = context.FPAbsNeg(srcB, absoluteB, negateB, fpType); - - Operand res = context.FPSaturate(context.FPAdd(srcA, srcB, fpType), saturate, fpType); - - SetDest(context, res, rd, isFP64); - - SetFPZnFlags(context, res, writeCC, fpType); - } - - private static void EmitFfma( - EmitterContext context, - Instruction fpType, - Operand srcA, - Operand srcB, - Operand srcC, - int rd, - bool negateB, - bool negateC, - bool saturate, - bool writeCC) - { - bool isFP64 = fpType == Instruction.FP64; - - srcB = context.FPNegate(srcB, negateB, fpType); - srcC = context.FPNegate(srcC, negateC, fpType); - - Operand res = context.FPSaturate(context.FPFusedMultiplyAdd(srcA, srcB, srcC, fpType), saturate, fpType); - - SetDest(context, res, rd, isFP64); - - SetFPZnFlags(context, res, writeCC, fpType); - } - - private static void EmitFmul( - EmitterContext context, - Instruction fpType, - MultiplyScale scale, - Operand srcA, - Operand srcB, - int rd, - bool negateB, - bool saturate, - bool writeCC) - { - bool isFP64 = fpType == Instruction.FP64; - - srcB = context.FPNegate(srcB, negateB, fpType); - - if (scale != MultiplyScale.NoScale) - { - Operand scaleConst = scale switch - { - MultiplyScale.D2 => ConstF(0.5f), - MultiplyScale.D4 => ConstF(0.25f), - MultiplyScale.D8 => ConstF(0.125f), - MultiplyScale.M2 => ConstF(2f), - MultiplyScale.M4 => ConstF(4f), - MultiplyScale.M8 => ConstF(8f), - _ => ConstF(1f) // Invalid, behave as if it had no scale. - }; - - if (scaleConst.AsFloat() == 1f) - { - context.Config.GpuAccessor.Log($"Invalid FP multiply scale \"{scale}\"."); - } - - if (isFP64) - { - scaleConst = context.FP32ConvertToFP64(scaleConst); - } - - srcA = context.FPMultiply(srcA, scaleConst, fpType); - } - - Operand res = context.FPSaturate(context.FPMultiply(srcA, srcB, fpType), saturate, fpType); - - SetDest(context, res, rd, isFP64); - - SetFPZnFlags(context, res, writeCC, fpType); - } - - private static void EmitHadd2Hmul2( - EmitterContext context, - OFmt swizzle, - Operand[] srcA, - Operand[] srcB, - bool isAdd, - int rd, - bool saturate) - { - Operand[] res = new Operand[2]; - - for (int index = 0; index < res.Length; index++) - { - if (isAdd) - { - res[index] = context.FPAdd(srcA[index], srcB[index]); - } - else - { - res[index] = context.FPMultiply(srcA[index], srcB[index]); - } - - res[index] = context.FPSaturate(res[index], saturate); - } - - context.Copy(GetDest(rd), GetHalfPacked(context, swizzle, res, rd)); - } - - public static void EmitHfma2( - EmitterContext context, - OFmt swizzle, - Operand[] srcA, - Operand[] srcB, - Operand[] srcC, - int rd, - bool saturate) - { - Operand[] res = new Operand[2]; - - for (int index = 0; index < res.Length; index++) - { - res[index] = context.FPFusedMultiplyAdd(srcA[index], srcB[index], srcC[index]); - res[index] = context.FPSaturate(res[index], saturate); - } - - context.Copy(GetDest(rd), GetHalfPacked(context, swizzle, res, rd)); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitFloatComparison.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitFloatComparison.cs deleted file mode 100644 index 8f99ddb3..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitFloatComparison.cs +++ /dev/null @@ -1,575 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; -using System; - -using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - public static void DsetR(EmitterContext context) - { - InstDsetR op = context.GetOp<InstDsetR>(); - - var srcA = GetSrcReg(context, op.SrcA, isFP64: true); - var srcB = GetSrcReg(context, op.SrcB, isFP64: true); - - EmitFset( - context, - op.FComp, - op.Bop, - srcA, - srcB, - op.SrcPred, - op.SrcPredInv, - op.Dest, - op.AbsA, - op.AbsB, - op.NegA, - op.NegB, - op.BVal, - op.WriteCC, - isFP64: true); - } - - public static void DsetI(EmitterContext context) - { - InstDsetI op = context.GetOp<InstDsetI>(); - - var srcA = GetSrcReg(context, op.SrcA, isFP64: true); - var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20), isFP64: true); - - EmitFset( - context, - op.FComp, - op.Bop, - srcA, - srcB, - op.SrcPred, - op.SrcPredInv, - op.Dest, - op.AbsA, - op.AbsB, - op.NegA, - op.NegB, - op.BVal, - op.WriteCC, - isFP64: true); - } - - public static void DsetC(EmitterContext context) - { - InstDsetC op = context.GetOp<InstDsetC>(); - - var srcA = GetSrcReg(context, op.SrcA, isFP64: true); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset, isFP64: true); - - EmitFset( - context, - op.FComp, - op.Bop, - srcA, - srcB, - op.SrcPred, - op.SrcPredInv, - op.Dest, - op.AbsA, - op.AbsB, - op.NegA, - op.NegB, - op.BVal, - op.WriteCC, - isFP64: true); - } - - public static void DsetpR(EmitterContext context) - { - InstDsetpR op = context.GetOp<InstDsetpR>(); - - var srcA = GetSrcReg(context, op.SrcA, isFP64: true); - var srcB = GetSrcReg(context, op.SrcB, isFP64: true); - - EmitFsetp( - context, - op.FComp, - op.Bop, - srcA, - srcB, - op.SrcPred, - op.SrcPredInv, - op.DestPred, - op.DestPredInv, - op.AbsA, - op.AbsB, - op.NegA, - op.NegB, - writeCC: false, - isFP64: true); - } - - public static void DsetpI(EmitterContext context) - { - InstDsetpI op = context.GetOp<InstDsetpI>(); - - var srcA = GetSrcReg(context, op.SrcA, isFP64: true); - var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20), isFP64: true); - - EmitFsetp( - context, - op.FComp, - op.Bop, - srcA, - srcB, - op.SrcPred, - op.SrcPredInv, - op.DestPred, - op.DestPredInv, - op.AbsA, - op.AbsB, - op.NegA, - op.NegB, - writeCC: false, - isFP64: true); - } - - public static void DsetpC(EmitterContext context) - { - InstDsetpC op = context.GetOp<InstDsetpC>(); - - var srcA = GetSrcReg(context, op.SrcA, isFP64: true); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset, isFP64: true); - - EmitFsetp( - context, - op.FComp, - op.Bop, - srcA, - srcB, - op.SrcPred, - op.SrcPredInv, - op.DestPred, - op.DestPredInv, - op.AbsA, - op.AbsB, - op.NegA, - op.NegB, - writeCC: false, - isFP64: true); - } - - public static void FcmpR(EmitterContext context) - { - InstFcmpR op = context.GetOp<InstFcmpR>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcB); - var srcC = GetSrcReg(context, op.SrcC); - - EmitFcmp(context, op.FComp, srcA, srcB, srcC, op.Dest); - } - - public static void FcmpI(EmitterContext context) - { - InstFcmpI op = context.GetOp<InstFcmpI>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20)); - var srcC = GetSrcReg(context, op.SrcC); - - EmitFcmp(context, op.FComp, srcA, srcB, srcC, op.Dest); - } - - public static void FcmpC(EmitterContext context) - { - InstFcmpC op = context.GetOp<InstFcmpC>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - var srcC = GetSrcReg(context, op.SrcC); - - EmitFcmp(context, op.FComp, srcA, srcB, srcC, op.Dest); - } - - public static void FcmpRc(EmitterContext context) - { - InstFcmpRc op = context.GetOp<InstFcmpRc>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcC); - var srcC = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - - EmitFcmp(context, op.FComp, srcA, srcB, srcC, op.Dest); - } - - public static void FsetR(EmitterContext context) - { - InstFsetR op = context.GetOp<InstFsetR>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcB); - - EmitFset(context, op.FComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.Dest, op.AbsA, op.AbsB, op.NegA, op.NegB, op.BVal, op.WriteCC); - } - - public static void FsetC(EmitterContext context) - { - InstFsetC op = context.GetOp<InstFsetC>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - - EmitFset(context, op.FComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.Dest, op.AbsA, op.AbsB, op.NegA, op.NegB, op.BVal, op.WriteCC); - } - - public static void FsetI(EmitterContext context) - { - InstFsetI op = context.GetOp<InstFsetI>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20)); - - EmitFset(context, op.FComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.Dest, op.AbsA, op.AbsB, op.NegA, op.NegB, op.BVal, op.WriteCC); - } - - public static void FsetpR(EmitterContext context) - { - InstFsetpR op = context.GetOp<InstFsetpR>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcB); - - EmitFsetp( - context, - op.FComp, - op.Bop, - srcA, - srcB, - op.SrcPred, - op.SrcPredInv, - op.DestPred, - op.DestPredInv, - op.AbsA, - op.AbsB, - op.NegA, - op.NegB, - op.WriteCC); - } - - public static void FsetpI(EmitterContext context) - { - InstFsetpI op = context.GetOp<InstFsetpI>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20)); - - EmitFsetp( - context, - op.FComp, - op.Bop, - srcA, - srcB, - op.SrcPred, - op.SrcPredInv, - op.DestPred, - op.DestPredInv, - op.AbsA, - op.AbsB, - op.NegA, - op.NegB, - op.WriteCC); - } - - public static void FsetpC(EmitterContext context) - { - InstFsetpC op = context.GetOp<InstFsetpC>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - - EmitFsetp( - context, - op.FComp, - op.Bop, - srcA, - srcB, - op.SrcPred, - op.SrcPredInv, - op.DestPred, - op.DestPredInv, - op.AbsA, - op.AbsB, - op.NegA, - op.NegB, - op.WriteCC); - } - - public static void Hset2R(EmitterContext context) - { - InstHset2R op = context.GetOp<InstHset2R>(); - - var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, op.AbsA); - var srcB = GetHalfSrc(context, op.BSwizzle, op.SrcB, op.NegB, op.AbsB); - - EmitHset2(context, op.Cmp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.Dest, op.Bval); - } - - public static void Hset2I(EmitterContext context) - { - InstHset2I op = context.GetOp<InstHset2I>(); - - var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, op.AbsA); - var srcB = GetHalfSrc(context, op.BimmH0, op.BimmH1); - - EmitHset2(context, op.Cmp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.Dest, op.Bval); - } - - public static void Hset2C(EmitterContext context) - { - InstHset2C op = context.GetOp<InstHset2C>(); - - var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, op.AbsA); - var srcB = GetHalfSrc(context, HalfSwizzle.F32, op.CbufSlot, op.CbufOffset, op.NegB, false); - - EmitHset2(context, op.Cmp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.Dest, op.Bval); - } - - public static void Hsetp2R(EmitterContext context) - { - InstHsetp2R op = context.GetOp<InstHsetp2R>(); - - var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, op.AbsA); - var srcB = GetHalfSrc(context, op.BSwizzle, op.SrcB, op.NegB, op.AbsB); - - EmitHsetp2(context, op.FComp2, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.DestPred, op.DestPredInv, op.HAnd); - } - - public static void Hsetp2I(EmitterContext context) - { - InstHsetp2I op = context.GetOp<InstHsetp2I>(); - - var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, op.AbsA); - var srcB = GetHalfSrc(context, op.BimmH0, op.BimmH1); - - EmitHsetp2(context, op.FComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.DestPred, op.DestPredInv, op.HAnd); - } - - public static void Hsetp2C(EmitterContext context) - { - InstHsetp2C op = context.GetOp<InstHsetp2C>(); - - var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, op.AbsA); - var srcB = GetHalfSrc(context, HalfSwizzle.F32, op.CbufSlot, op.CbufOffset, op.NegB, op.AbsB); - - EmitHsetp2(context, op.FComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.DestPred, op.DestPredInv, op.HAnd); - } - - private static void EmitFcmp(EmitterContext context, FComp cmpOp, Operand srcA, Operand srcB, Operand srcC, int rd) - { - Operand cmpRes = GetFPComparison(context, cmpOp, srcC, ConstF(0)); - - Operand res = context.ConditionalSelect(cmpRes, srcA, srcB); - - context.Copy(GetDest(rd), res); - } - - private static void EmitFset( - EmitterContext context, - FComp cmpOp, - BoolOp logicOp, - Operand srcA, - Operand srcB, - int srcPred, - bool srcPredInv, - int rd, - bool absoluteA, - bool absoluteB, - bool negateA, - bool negateB, - bool boolFloat, - bool writeCC, - bool isFP64 = false) - { - Instruction fpType = isFP64 ? Instruction.FP64 : Instruction.FP32; - - srcA = context.FPAbsNeg(srcA, absoluteA, negateA, fpType); - srcB = context.FPAbsNeg(srcB, absoluteB, negateB, fpType); - - Operand res = GetFPComparison(context, cmpOp, srcA, srcB, fpType); - Operand pred = GetPredicate(context, srcPred, srcPredInv); - - res = GetPredLogicalOp(context, logicOp, res, pred); - - Operand dest = GetDest(rd); - - if (boolFloat) - { - res = context.ConditionalSelect(res, ConstF(1), Const(0)); - - context.Copy(dest, res); - - SetFPZnFlags(context, res, writeCC); - } - else - { - context.Copy(dest, res); - - SetZnFlags(context, res, writeCC, extended: false); - } - } - - private static void EmitFsetp( - EmitterContext context, - FComp cmpOp, - BoolOp logicOp, - Operand srcA, - Operand srcB, - int srcPred, - bool srcPredInv, - int destPred, - int destPredInv, - bool absoluteA, - bool absoluteB, - bool negateA, - bool negateB, - bool writeCC, - bool isFP64 = false) - { - Instruction fpType = isFP64 ? Instruction.FP64 : Instruction.FP32; - - srcA = context.FPAbsNeg(srcA, absoluteA, negateA, fpType); - srcB = context.FPAbsNeg(srcB, absoluteB, negateB, fpType); - - Operand p0Res = GetFPComparison(context, cmpOp, srcA, srcB, fpType); - Operand p1Res = context.BitwiseNot(p0Res); - Operand pred = GetPredicate(context, srcPred, srcPredInv); - - p0Res = GetPredLogicalOp(context, logicOp, p0Res, pred); - p1Res = GetPredLogicalOp(context, logicOp, p1Res, pred); - - context.Copy(Register(destPred, RegisterType.Predicate), p0Res); - context.Copy(Register(destPredInv, RegisterType.Predicate), p1Res); - } - - private static void EmitHset2( - EmitterContext context, - FComp cmpOp, - BoolOp logicOp, - Operand[] srcA, - Operand[] srcB, - int srcPred, - bool srcPredInv, - int rd, - bool boolFloat) - { - Operand[] res = new Operand[2]; - - res[0] = GetFPComparison(context, cmpOp, srcA[0], srcB[0]); - res[1] = GetFPComparison(context, cmpOp, srcA[1], srcB[1]); - - Operand pred = GetPredicate(context, srcPred, srcPredInv); - - res[0] = GetPredLogicalOp(context, logicOp, res[0], pred); - res[1] = GetPredLogicalOp(context, logicOp, res[1], pred); - - if (boolFloat) - { - res[0] = context.ConditionalSelect(res[0], ConstF(1), Const(0)); - res[1] = context.ConditionalSelect(res[1], ConstF(1), Const(0)); - - context.Copy(GetDest(rd), context.PackHalf2x16(res[0], res[1])); - } - else - { - Operand low = context.BitwiseAnd(res[0], Const(0xffff)); - Operand high = context.ShiftLeft (res[1], Const(16)); - - Operand packed = context.BitwiseOr(low, high); - - context.Copy(GetDest(rd), packed); - } - } - - private static void EmitHsetp2( - EmitterContext context, - FComp cmpOp, - BoolOp logicOp, - Operand[] srcA, - Operand[] srcB, - int srcPred, - bool srcPredInv, - int destPred, - int destPredInv, - bool hAnd) - { - Operand p0Res = GetFPComparison(context, cmpOp, srcA[0], srcB[0]); - Operand p1Res = GetFPComparison(context, cmpOp, srcA[1], srcB[1]); - - if (hAnd) - { - p0Res = context.BitwiseAnd(p0Res, p1Res); - p1Res = context.BitwiseNot(p0Res); - } - - Operand pred = GetPredicate(context, srcPred, srcPredInv); - - p0Res = GetPredLogicalOp(context, logicOp, p0Res, pred); - p1Res = GetPredLogicalOp(context, logicOp, p1Res, pred); - - context.Copy(Register(destPred, RegisterType.Predicate), p0Res); - context.Copy(Register(destPredInv, RegisterType.Predicate), p1Res); - } - - private static Operand GetFPComparison(EmitterContext context, FComp cond, Operand srcA, Operand srcB, Instruction fpType = Instruction.FP32) - { - Operand res; - - if (cond == FComp.T) - { - res = Const(IrConsts.True); - } - else if (cond == FComp.F) - { - res = Const(IrConsts.False); - } - else if (cond == FComp.Nan || cond == FComp.Num) - { - res = context.BitwiseOr(context.IsNan(srcA, fpType), context.IsNan(srcB, fpType)); - - if (cond == FComp.Num) - { - res = context.BitwiseNot(res); - } - } - else - { - Instruction inst; - - switch (cond & ~FComp.Nan) - { - case FComp.Lt: inst = Instruction.CompareLess; break; - case FComp.Eq: inst = Instruction.CompareEqual; break; - case FComp.Le: inst = Instruction.CompareLessOrEqual; break; - case FComp.Gt: inst = Instruction.CompareGreater; break; - case FComp.Ne: inst = Instruction.CompareNotEqual; break; - case FComp.Ge: inst = Instruction.CompareGreaterOrEqual; break; - - default: throw new ArgumentException($"Unexpected condition \"{cond}\"."); - } - - res = context.Add(inst | fpType, Local(), srcA, srcB); - - if ((cond & FComp.Nan) != 0) - { - res = context.BitwiseOr(res, context.IsNan(srcA, fpType)); - res = context.BitwiseOr(res, context.IsNan(srcB, fpType)); - } - } - - return res; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitFloatMinMax.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitFloatMinMax.cs deleted file mode 100644 index 412a5305..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitFloatMinMax.cs +++ /dev/null @@ -1,106 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; - -using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - public static void DmnmxR(EmitterContext context) - { - InstDmnmxR op = context.GetOp<InstDmnmxR>(); - - var srcA = GetSrcReg(context, op.SrcA, isFP64: true); - var srcB = GetSrcReg(context, op.SrcB, isFP64: true); - var srcPred = GetPredicate(context, op.SrcPred, op.SrcPredInv); - - EmitFmnmx(context, srcA, srcB, srcPred, op.Dest, op.AbsA, op.AbsB, op.NegA, op.NegB, op.WriteCC, isFP64: true); - } - - public static void DmnmxI(EmitterContext context) - { - InstDmnmxI op = context.GetOp<InstDmnmxI>(); - - var srcA = GetSrcReg(context, op.SrcA, isFP64: true); - var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20), isFP64: true); - var srcPred = GetPredicate(context, op.SrcPred, op.SrcPredInv); - - EmitFmnmx(context, srcA, srcB, srcPred, op.Dest, op.AbsA, op.AbsB, op.NegA, op.NegB, op.WriteCC, isFP64: true); - } - - public static void DmnmxC(EmitterContext context) - { - InstDmnmxC op = context.GetOp<InstDmnmxC>(); - - var srcA = GetSrcReg(context, op.SrcA, isFP64: true); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset, isFP64: true); - var srcPred = GetPredicate(context, op.SrcPred, op.SrcPredInv); - - EmitFmnmx(context, srcA, srcB, srcPred, op.Dest, op.AbsA, op.AbsB, op.NegA, op.NegB, op.WriteCC, isFP64: true); - } - - public static void FmnmxR(EmitterContext context) - { - InstFmnmxR op = context.GetOp<InstFmnmxR>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcB); - var srcPred = GetPredicate(context, op.SrcPred, op.SrcPredInv); - - EmitFmnmx(context, srcA, srcB, srcPred, op.Dest, op.AbsA, op.AbsB, op.NegA, op.NegB, op.WriteCC); - } - - public static void FmnmxI(EmitterContext context) - { - InstFmnmxI op = context.GetOp<InstFmnmxI>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20)); - var srcPred = GetPredicate(context, op.SrcPred, op.SrcPredInv); - - EmitFmnmx(context, srcA, srcB, srcPred, op.Dest, op.AbsA, op.AbsB, op.NegA, op.NegB, op.WriteCC); - } - - public static void FmnmxC(EmitterContext context) - { - InstFmnmxC op = context.GetOp<InstFmnmxC>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - var srcPred = GetPredicate(context, op.SrcPred, op.SrcPredInv); - - EmitFmnmx(context, srcA, srcB, srcPred, op.Dest, op.AbsA, op.AbsB, op.NegA, op.NegB, op.WriteCC); - } - - private static void EmitFmnmx( - EmitterContext context, - Operand srcA, - Operand srcB, - Operand srcPred, - int rd, - bool absoluteA, - bool absoluteB, - bool negateA, - bool negateB, - bool writeCC, - bool isFP64 = false) - { - Instruction fpType = isFP64 ? Instruction.FP64 : Instruction.FP32; - - srcA = context.FPAbsNeg(srcA, absoluteA, negateA, fpType); - srcB = context.FPAbsNeg(srcB, absoluteB, negateB, fpType); - - Operand resMin = context.FPMinimum(srcA, srcB, fpType); - Operand resMax = context.FPMaximum(srcA, srcB, fpType); - - Operand res = context.ConditionalSelect(srcPred, resMin, resMax); - - SetDest(context, res, rd, isFP64); - - SetFPZnFlags(context, res, writeCC, fpType); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitFlowControl.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitFlowControl.cs deleted file mode 100644 index 91c23230..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitFlowControl.cs +++ /dev/null @@ -1,322 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; -using System.Collections.Generic; -using System.Linq; - -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - public static void Bra(EmitterContext context) - { - InstBra op = context.GetOp<InstBra>(); - - EmitBranch(context, context.CurrBlock.Successors[^1].Address); - } - - public static void Brk(EmitterContext context) - { - InstBrk op = context.GetOp<InstBrk>(); - - EmitBrkContSync(context); - } - - public static void Brx(EmitterContext context) - { - InstBrx op = context.GetOp<InstBrx>(); - InstOp currOp = context.CurrOp; - int startIndex = context.CurrBlock.HasNext() ? 1 : 0; - - if (context.CurrBlock.Successors.Count <= startIndex) - { - context.Config.GpuAccessor.Log($"Failed to find targets for BRX instruction at 0x{currOp.Address:X}."); - return; - } - - int offset = (int)currOp.GetAbsoluteAddress(); - - Operand address = context.IAdd(Register(op.SrcA, RegisterType.Gpr), Const(offset)); - - var targets = context.CurrBlock.Successors.Skip(startIndex); - - bool allTargetsSinglePred = true; - int total = context.CurrBlock.Successors.Count - startIndex; - int count = 0; - - foreach (var target in targets.OrderBy(x => x.Address)) - { - if (++count < total && (target.Predecessors.Count > 1 || target.Address <= context.CurrBlock.Address)) - { - allTargetsSinglePred = false; - break; - } - } - - if (allTargetsSinglePred) - { - // Chain blocks, each target block will check if the BRX target address - // matches its own address, if not, it jumps to the next target which will do the same check, - // until it reaches the last possible target, which executed unconditionally. - // We can only do this if the BRX block is the only predecessor of all target blocks. - // Additionally, this is not supported for blocks located before the current block, - // since it will be too late to insert a label, but this is something that can be improved - // in the future if necessary. - - var sortedTargets = targets.OrderBy(x => x.Address); - - Block currentTarget = null; - ulong firstTargetAddress = 0; - - foreach (Block nextTarget in sortedTargets) - { - if (currentTarget != null) - { - if (currentTarget.Address != nextTarget.Address) - { - context.SetBrxTarget(currentTarget.Address, address, (int)currentTarget.Address, nextTarget.Address); - } - } - else - { - firstTargetAddress = nextTarget.Address; - } - - currentTarget = nextTarget; - } - - context.Branch(context.GetLabel(firstTargetAddress)); - } - else - { - // Emit the branches sequentially. - // This generates slightly worse code, but should work for all cases. - - var sortedTargets = targets.OrderByDescending(x => x.Address); - ulong lastTargetAddress = ulong.MaxValue; - - count = 0; - - foreach (Block target in sortedTargets) - { - Operand label = context.GetLabel(target.Address); - - if (++count < total) - { - if (target.Address != lastTargetAddress) - { - context.BranchIfTrue(label, context.ICompareEqual(address, Const((int)target.Address))); - } - - lastTargetAddress = target.Address; - } - else - { - context.Branch(label); - } - } - } - } - - public static void Cal(EmitterContext context) - { - InstCal op = context.GetOp<InstCal>(); - - DecodedFunction function = context.Program.GetFunctionByAddress(context.CurrOp.GetAbsoluteAddress()); - - if (function.IsCompilerGenerated) - { - switch (function.Type) - { - case FunctionType.BuiltInFSIBegin: - context.FSIBegin(); - break; - case FunctionType.BuiltInFSIEnd: - context.FSIEnd(); - break; - } - } - else - { - context.Call(function.Id, false); - } - } - - public static void Cont(EmitterContext context) - { - InstCont op = context.GetOp<InstCont>(); - - EmitBrkContSync(context); - } - - public static void Exit(EmitterContext context) - { - InstExit op = context.GetOp<InstExit>(); - - if (context.IsNonMain) - { - context.Config.GpuAccessor.Log("Invalid exit on non-main function."); - return; - } - - if (op.Ccc == Ccc.T) - { - context.Return(); - } - else - { - Operand cond = GetCondition(context, op.Ccc, IrConsts.False); - - // If the condition is always false, we don't need to do anything. - if (cond.Type != OperandType.Constant || cond.Value != IrConsts.False) - { - Operand lblSkip = Label(); - context.BranchIfFalse(lblSkip, cond); - context.Return(); - context.MarkLabel(lblSkip); - } - } - } - - public static void Kil(EmitterContext context) - { - InstKil op = context.GetOp<InstKil>(); - - context.Discard(); - } - - public static void Pbk(EmitterContext context) - { - InstPbk op = context.GetOp<InstPbk>(); - - EmitPbkPcntSsy(context); - } - - public static void Pcnt(EmitterContext context) - { - InstPcnt op = context.GetOp<InstPcnt>(); - - EmitPbkPcntSsy(context); - } - - public static void Ret(EmitterContext context) - { - InstRet op = context.GetOp<InstRet>(); - - if (context.IsNonMain) - { - context.Return(); - } - else - { - context.Config.GpuAccessor.Log("Invalid return on main function."); - } - } - - public static void Ssy(EmitterContext context) - { - InstSsy op = context.GetOp<InstSsy>(); - - EmitPbkPcntSsy(context); - } - - public static void Sync(EmitterContext context) - { - InstSync op = context.GetOp<InstSync>(); - - EmitBrkContSync(context); - } - - private static void EmitPbkPcntSsy(EmitterContext context) - { - var consumers = context.CurrBlock.PushOpCodes.First(x => x.Op.Address == context.CurrOp.Address).Consumers; - - foreach (KeyValuePair<Block, Operand> kv in consumers) - { - Block consumerBlock = kv.Key; - Operand local = kv.Value; - - int id = consumerBlock.SyncTargets[context.CurrOp.Address].PushOpId; - - context.Copy(local, Const(id)); - } - } - - private static void EmitBrkContSync(EmitterContext context) - { - var targets = context.CurrBlock.SyncTargets; - - if (targets.Count == 1) - { - // If we have only one target, then the SSY/PBK is basically - // a branch, we can produce better codegen for this case. - EmitBranch(context, targets.Values.First().PushOpInfo.Op.GetAbsoluteAddress()); - } - else - { - // TODO: Support CC here as well (condition). - foreach (SyncTarget target in targets.Values) - { - PushOpInfo pushOpInfo = target.PushOpInfo; - - Operand label = context.GetLabel(pushOpInfo.Op.GetAbsoluteAddress()); - Operand local = pushOpInfo.Consumers[context.CurrBlock]; - - context.BranchIfTrue(label, context.ICompareEqual(local, Const(target.PushOpId))); - } - } - } - - private static void EmitBranch(EmitterContext context, ulong address) - { - InstOp op = context.CurrOp; - InstConditional opCond = new InstConditional(op.RawOpCode); - - // If we're branching to the next instruction, then the branch - // is useless and we can ignore it. - if (address == op.Address + 8) - { - return; - } - - Operand label = context.GetLabel(address); - - Operand pred = Register(opCond.Pred, RegisterType.Predicate); - - if (opCond.Ccc != Ccc.T) - { - Operand cond = GetCondition(context, opCond.Ccc); - - if (opCond.Pred == RegisterConsts.PredicateTrueIndex) - { - pred = cond; - } - else if (opCond.PredInv) - { - pred = context.BitwiseAnd(context.BitwiseNot(pred), cond); - } - else - { - pred = context.BitwiseAnd(pred, cond); - } - - context.BranchIfTrue(label, pred); - } - else if (opCond.Pred == RegisterConsts.PredicateTrueIndex) - { - context.Branch(label); - } - else if (opCond.PredInv) - { - context.BranchIfFalse(label, pred); - } - else - { - context.BranchIfTrue(label, pred); - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitHelper.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitHelper.cs deleted file mode 100644 index 0ba4667e..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitHelper.cs +++ /dev/null @@ -1,266 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; -using System; -using System.Runtime.CompilerServices; - -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static class InstEmitHelper - { - public static Operand GetZF() - { - return Register(0, RegisterType.Flag); - } - - public static Operand GetNF() - { - return Register(1, RegisterType.Flag); - } - - public static Operand GetCF() - { - return Register(2, RegisterType.Flag); - } - - public static Operand GetVF() - { - return Register(3, RegisterType.Flag); - } - - public static Operand GetDest(int rd) - { - return Register(rd, RegisterType.Gpr); - } - - public static Operand GetDest2(int rd) - { - return Register(rd | 1, RegisterType.Gpr); - } - - public static Operand GetSrcCbuf(EmitterContext context, int cbufSlot, int cbufOffset, bool isFP64 = false) - { - if (isFP64) - { - return context.PackDouble2x32( - Cbuf(cbufSlot, cbufOffset), - Cbuf(cbufSlot, cbufOffset + 1)); - } - else - { - return Cbuf(cbufSlot, cbufOffset); - } - } - - public static Operand GetSrcImm(EmitterContext context, int imm, bool isFP64 = false) - { - if (isFP64) - { - return context.PackDouble2x32(Const(0), Const(imm)); - } - else - { - return Const(imm); - } - } - - public static Operand GetSrcReg(EmitterContext context, int reg, bool isFP64 = false) - { - if (isFP64) - { - return context.PackDouble2x32(Register(reg, RegisterType.Gpr), Register(reg | 1, RegisterType.Gpr)); - } - else - { - return Register(reg, RegisterType.Gpr); - } - } - - public static Operand[] GetHalfSrc( - EmitterContext context, - HalfSwizzle swizzle, - int ra, - bool negate, - bool absolute) - { - Operand[] operands = GetHalfUnpacked(context, GetSrcReg(context, ra), swizzle); - - return FPAbsNeg(context, operands, absolute, negate); - } - - public static Operand[] GetHalfSrc( - EmitterContext context, - HalfSwizzle swizzle, - int cbufSlot, - int cbufOffset, - bool negate, - bool absolute) - { - Operand[] operands = GetHalfUnpacked(context, GetSrcCbuf(context, cbufSlot, cbufOffset), swizzle); - - return FPAbsNeg(context, operands, absolute, negate); - } - - public static Operand[] GetHalfSrc(EmitterContext context, int immH0, int immH1) - { - ushort low = (ushort)(immH0 << 6); - ushort high = (ushort)(immH1 << 6); - - return new Operand[] - { - ConstF((float)Unsafe.As<ushort, Half>(ref low)), - ConstF((float)Unsafe.As<ushort, Half>(ref high)) - }; - } - - public static Operand[] GetHalfSrc(EmitterContext context, int imm32) - { - ushort low = (ushort)imm32; - ushort high = (ushort)(imm32 >> 16); - - return new Operand[] - { - ConstF((float)Unsafe.As<ushort, Half>(ref low)), - ConstF((float)Unsafe.As<ushort, Half>(ref high)) - }; - } - - public static Operand[] FPAbsNeg(EmitterContext context, Operand[] operands, bool abs, bool neg) - { - for (int index = 0; index < operands.Length; index++) - { - operands[index] = context.FPAbsNeg(operands[index], abs, neg); - } - - return operands; - } - - public static Operand[] GetHalfUnpacked(EmitterContext context, Operand src, HalfSwizzle swizzle) - { - switch (swizzle) - { - case HalfSwizzle.F16: - return new Operand[] - { - context.UnpackHalf2x16Low (src), - context.UnpackHalf2x16High(src) - }; - - case HalfSwizzle.F32: return new Operand[] { src, src }; - - case HalfSwizzle.H0H0: - return new Operand[] - { - context.UnpackHalf2x16Low(src), - context.UnpackHalf2x16Low(src) - }; - - case HalfSwizzle.H1H1: - return new Operand[] - { - context.UnpackHalf2x16High(src), - context.UnpackHalf2x16High(src) - }; - } - - throw new ArgumentException($"Invalid swizzle \"{swizzle}\"."); - } - - public static Operand GetHalfPacked(EmitterContext context, OFmt swizzle, Operand[] results, int rd) - { - switch (swizzle) - { - case OFmt.F16: return context.PackHalf2x16(results[0], results[1]); - - case OFmt.F32: return results[0]; - - case OFmt.MrgH0: - { - Operand h1 = GetHalfDest(context, rd, isHigh: true); - - return context.PackHalf2x16(results[0], h1); - } - - case OFmt.MrgH1: - { - Operand h0 = GetHalfDest(context, rd, isHigh: false); - - return context.PackHalf2x16(h0, results[1]); - } - } - - throw new ArgumentException($"Invalid swizzle \"{swizzle}\"."); - } - - public static Operand GetHalfDest(EmitterContext context, int rd, bool isHigh) - { - if (isHigh) - { - return context.UnpackHalf2x16High(GetDest(rd)); - } - else - { - return context.UnpackHalf2x16Low(GetDest(rd)); - } - } - - public static Operand GetPredicate(EmitterContext context, int pred, bool not) - { - Operand local = Register(pred, RegisterType.Predicate); - - if (not) - { - local = context.BitwiseNot(local); - } - - return local; - } - - public static void SetDest(EmitterContext context, Operand value, int rd, bool isFP64) - { - if (isFP64) - { - context.Copy(GetDest(rd), context.UnpackDouble2x32Low(value)); - context.Copy(GetDest2(rd), context.UnpackDouble2x32High(value)); - } - else - { - context.Copy(GetDest(rd), value); - } - } - - public static int Imm16ToSInt(int imm16) - { - return (short)imm16; - } - - public static int Imm20ToFloat(int imm20) - { - return imm20 << 12; - } - - public static int Imm20ToSInt(int imm20) - { - return (imm20 << 12) >> 12; - } - - public static int Imm24ToSInt(int imm24) - { - return (imm24 << 8) >> 8; - } - - public static Operand SignExtendTo32(EmitterContext context, Operand src, int srcBits) - { - return context.BitfieldExtractS32(src, Const(0), Const(srcBits)); - } - - public static Operand ZeroExtendTo32(EmitterContext context, Operand src, int srcBits) - { - int mask = (int)(uint.MaxValue >> (32 - srcBits)); - - return context.BitwiseAnd(src, Const(mask)); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerArithmetic.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerArithmetic.cs deleted file mode 100644 index 374e3d61..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerArithmetic.cs +++ /dev/null @@ -1,699 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; - -using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - public static void IaddR(EmitterContext context) - { - InstIaddR op = context.GetOp<InstIaddR>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcB); - - EmitIadd(context, srcA, srcB, op.Dest, op.AvgMode, op.X, op.WriteCC); - } - - public static void IaddI(EmitterContext context) - { - InstIaddI op = context.GetOp<InstIaddI>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); - - EmitIadd(context, srcA, srcB, op.Dest, op.AvgMode, op.X, op.WriteCC); - } - - public static void IaddC(EmitterContext context) - { - InstIaddC op = context.GetOp<InstIaddC>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - - EmitIadd(context, srcA, srcB, op.Dest, op.AvgMode, op.X, op.WriteCC); - } - - public static void Iadd32i(EmitterContext context) - { - InstIadd32i op = context.GetOp<InstIadd32i>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, op.Imm32); - - EmitIadd(context, srcA, srcB, op.Dest, op.AvgMode, op.X, op.WriteCC); - } - - public static void Iadd3R(EmitterContext context) - { - InstIadd3R op = context.GetOp<InstIadd3R>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcB); - var srcC = GetSrcReg(context, op.SrcC); - - EmitIadd3(context, op.Lrs, srcA, srcB, srcC, op.Apart, op.Bpart, op.Cpart, op.Dest, op.NegA, op.NegB, op.NegC); - } - - public static void Iadd3I(EmitterContext context) - { - InstIadd3I op = context.GetOp<InstIadd3I>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); - var srcC = GetSrcReg(context, op.SrcC); - - EmitIadd3(context, Lrs.None, srcA, srcB, srcC, HalfSelect.B32, HalfSelect.B32, HalfSelect.B32, op.Dest, op.NegA, op.NegB, op.NegC); - } - - public static void Iadd3C(EmitterContext context) - { - InstIadd3C op = context.GetOp<InstIadd3C>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - var srcC = GetSrcReg(context, op.SrcC); - - EmitIadd3(context, Lrs.None, srcA, srcB, srcC, HalfSelect.B32, HalfSelect.B32, HalfSelect.B32, op.Dest, op.NegA, op.NegB, op.NegC); - } - - public static void ImadR(EmitterContext context) - { - InstImadR op = context.GetOp<InstImadR>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcB); - var srcC = GetSrcReg(context, op.SrcC); - - EmitImad(context, srcA, srcB, srcC, op.Dest, op.AvgMode, op.ASigned, op.BSigned, op.Hilo); - } - - public static void ImadI(EmitterContext context) - { - InstImadI op = context.GetOp<InstImadI>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); - var srcC = GetSrcReg(context, op.SrcC); - - EmitImad(context, srcA, srcB, srcC, op.Dest, op.AvgMode, op.ASigned, op.BSigned, op.Hilo); - } - - public static void ImadC(EmitterContext context) - { - InstImadC op = context.GetOp<InstImadC>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - var srcC = GetSrcReg(context, op.SrcC); - - EmitImad(context, srcA, srcB, srcC, op.Dest, op.AvgMode, op.ASigned, op.BSigned, op.Hilo); - } - - public static void ImadRc(EmitterContext context) - { - InstImadRc op = context.GetOp<InstImadRc>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcC); - var srcC = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - - EmitImad(context, srcA, srcB, srcC, op.Dest, op.AvgMode, op.ASigned, op.BSigned, op.Hilo); - } - - public static void Imad32i(EmitterContext context) - { - InstImad32i op = context.GetOp<InstImad32i>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, op.Imm32); - var srcC = GetSrcReg(context, op.Dest); - - EmitImad(context, srcA, srcB, srcC, op.Dest, op.AvgMode, op.ASigned, op.BSigned, op.Hilo); - } - - public static void ImulR(EmitterContext context) - { - InstImulR op = context.GetOp<InstImulR>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcB); - - EmitImad(context, srcA, srcB, Const(0), op.Dest, AvgMode.NoNeg, op.ASigned, op.BSigned, op.Hilo); - } - - public static void ImulI(EmitterContext context) - { - InstImulI op = context.GetOp<InstImulI>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); - - EmitImad(context, srcA, srcB, Const(0), op.Dest, AvgMode.NoNeg, op.ASigned, op.BSigned, op.Hilo); - } - - public static void ImulC(EmitterContext context) - { - InstImulC op = context.GetOp<InstImulC>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - - EmitImad(context, srcA, srcB, Const(0), op.Dest, AvgMode.NoNeg, op.ASigned, op.BSigned, op.Hilo); - } - - public static void Imul32i(EmitterContext context) - { - InstImul32i op = context.GetOp<InstImul32i>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, op.Imm32); - - EmitImad(context, srcA, srcB, Const(0), op.Dest, AvgMode.NoNeg, op.ASigned, op.BSigned, op.Hilo); - } - - public static void IscaddR(EmitterContext context) - { - InstIscaddR op = context.GetOp<InstIscaddR>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcB); - - EmitIscadd(context, srcA, srcB, op.Dest, op.Imm5, op.AvgMode, op.WriteCC); - } - - public static void IscaddI(EmitterContext context) - { - InstIscaddI op = context.GetOp<InstIscaddI>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); - - EmitIscadd(context, srcA, srcB, op.Dest, op.Imm5, op.AvgMode, op.WriteCC); - } - - public static void IscaddC(EmitterContext context) - { - InstIscaddC op = context.GetOp<InstIscaddC>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - - EmitIscadd(context, srcA, srcB, op.Dest, op.Imm5, op.AvgMode, op.WriteCC); - } - - public static void Iscadd32i(EmitterContext context) - { - InstIscadd32i op = context.GetOp<InstIscadd32i>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, op.Imm32); - - EmitIscadd(context, srcA, srcB, op.Dest, op.Imm5, AvgMode.NoNeg, op.WriteCC); - } - - public static void LeaR(EmitterContext context) - { - InstLeaR op = context.GetOp<InstLeaR>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcB); - - EmitLea(context, srcA, srcB, op.Dest, op.NegA, op.ImmU5); - } - - public static void LeaI(EmitterContext context) - { - InstLeaI op = context.GetOp<InstLeaI>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); - - EmitLea(context, srcA, srcB, op.Dest, op.NegA, op.ImmU5); - } - - public static void LeaC(EmitterContext context) - { - InstLeaC op = context.GetOp<InstLeaC>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - - EmitLea(context, srcA, srcB, op.Dest, op.NegA, op.ImmU5); - } - - public static void LeaHiR(EmitterContext context) - { - InstLeaHiR op = context.GetOp<InstLeaHiR>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcB); - var srcC = GetSrcReg(context, op.SrcC); - - EmitLeaHi(context, srcA, srcB, srcC, op.Dest, op.NegA, op.ImmU5); - } - - public static void LeaHiC(EmitterContext context) - { - InstLeaHiC op = context.GetOp<InstLeaHiC>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - var srcC = GetSrcReg(context, op.SrcC); - - EmitLeaHi(context, srcA, srcB, srcC, op.Dest, op.NegA, op.ImmU5); - } - - public static void XmadR(EmitterContext context) - { - InstXmadR op = context.GetOp<InstXmadR>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcB); - var srcC = GetSrcReg(context, op.SrcC); - - EmitXmad(context, op.XmadCop, srcA, srcB, srcC, op.Dest, op.ASigned, op.BSigned, op.HiloA, op.HiloB, op.Psl, op.Mrg, op.X, op.WriteCC); - } - - public static void XmadI(EmitterContext context) - { - InstXmadI op = context.GetOp<InstXmadI>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, op.Imm16); - var srcC = GetSrcReg(context, op.SrcC); - - EmitXmad(context, op.XmadCop, srcA, srcB, srcC, op.Dest, op.ASigned, op.BSigned, op.HiloA, false, op.Psl, op.Mrg, op.X, op.WriteCC); - } - - public static void XmadC(EmitterContext context) - { - InstXmadC op = context.GetOp<InstXmadC>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - var srcC = GetSrcReg(context, op.SrcC); - - EmitXmad(context, op.XmadCop, srcA, srcB, srcC, op.Dest, op.ASigned, op.BSigned, op.HiloA, op.HiloB, op.Psl, op.Mrg, op.X, op.WriteCC); - } - - public static void XmadRc(EmitterContext context) - { - InstXmadRc op = context.GetOp<InstXmadRc>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcC); - var srcC = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - - EmitXmad(context, op.XmadCop, srcA, srcB, srcC, op.Dest, op.ASigned, op.BSigned, op.HiloA, op.HiloB, false, false, op.X, op.WriteCC); - } - - private static void EmitIadd( - EmitterContext context, - Operand srcA, - Operand srcB, - int rd, - AvgMode avgMode, - bool extended, - bool writeCC) - { - srcA = context.INegate(srcA, avgMode == AvgMode.NegA); - srcB = context.INegate(srcB, avgMode == AvgMode.NegB); - - Operand res = context.IAdd(srcA, srcB); - - if (extended) - { - res = context.IAdd(res, context.BitwiseAnd(GetCF(), Const(1))); - } - - SetIaddFlags(context, res, srcA, srcB, writeCC, extended); - - // TODO: SAT. - - context.Copy(GetDest(rd), res); - } - - private static void EmitIadd3( - EmitterContext context, - Lrs mode, - Operand srcA, - Operand srcB, - Operand srcC, - HalfSelect partA, - HalfSelect partB, - HalfSelect partC, - int rd, - bool negateA, - bool negateB, - bool negateC) - { - Operand Extend(Operand src, HalfSelect part) - { - if (part == HalfSelect.B32) - { - return src; - } - - if (part == HalfSelect.H0) - { - return context.BitwiseAnd(src, Const(0xffff)); - } - else if (part == HalfSelect.H1) - { - return context.ShiftRightU32(src, Const(16)); - } - else - { - context.Config.GpuAccessor.Log($"Iadd3 has invalid component selection {part}."); - } - - return src; - } - - srcA = context.INegate(Extend(srcA, partA), negateA); - srcB = context.INegate(Extend(srcB, partB), negateB); - srcC = context.INegate(Extend(srcC, partC), negateC); - - Operand res = context.IAdd(srcA, srcB); - - if (mode != Lrs.None) - { - if (mode == Lrs.LeftShift) - { - res = context.ShiftLeft(res, Const(16)); - } - else if (mode == Lrs.RightShift) - { - res = context.ShiftRightU32(res, Const(16)); - } - else - { - // TODO: Warning. - } - } - - res = context.IAdd(res, srcC); - - context.Copy(GetDest(rd), res); - - // TODO: CC, X, corner cases. - } - - private static void EmitImad( - EmitterContext context, - Operand srcA, - Operand srcB, - Operand srcC, - int rd, - AvgMode avgMode, - bool signedA, - bool signedB, - bool high) - { - srcB = context.INegate(srcB, avgMode == AvgMode.NegA); - srcC = context.INegate(srcC, avgMode == AvgMode.NegB); - - Operand res; - - if (high) - { - if (signedA && signedB) - { - res = context.MultiplyHighS32(srcA, srcB); - } - else - { - res = context.MultiplyHighU32(srcA, srcB); - - if (signedA) - { - res = context.IAdd(res, context.IMultiply(srcB, context.ShiftRightS32(srcA, Const(31)))); - } - else if (signedB) - { - res = context.IAdd(res, context.IMultiply(srcA, context.ShiftRightS32(srcB, Const(31)))); - } - } - } - else - { - res = context.IMultiply(srcA, srcB); - } - - if (srcC.Type != OperandType.Constant || srcC.Value != 0) - { - res = context.IAdd(res, srcC); - } - - // TODO: CC, X, SAT, and more? - - context.Copy(GetDest(rd), res); - } - - private static void EmitIscadd( - EmitterContext context, - Operand srcA, - Operand srcB, - int rd, - int shift, - AvgMode avgMode, - bool writeCC) - { - srcA = context.ShiftLeft(srcA, Const(shift)); - - srcA = context.INegate(srcA, avgMode == AvgMode.NegA); - srcB = context.INegate(srcB, avgMode == AvgMode.NegB); - - Operand res = context.IAdd(srcA, srcB); - - SetIaddFlags(context, res, srcA, srcB, writeCC, false); - - context.Copy(GetDest(rd), res); - } - - public static void EmitLea(EmitterContext context, Operand srcA, Operand srcB, int rd, bool negateA, int shift) - { - srcA = context.ShiftLeft(srcA, Const(shift)); - srcA = context.INegate(srcA, negateA); - - Operand res = context.IAdd(srcA, srcB); - - context.Copy(GetDest(rd), res); - - // TODO: CC, X. - } - - private static void EmitLeaHi( - EmitterContext context, - Operand srcA, - Operand srcB, - Operand srcC, - int rd, - bool negateA, - int shift) - { - Operand aLow = context.ShiftLeft(srcA, Const(shift)); - Operand aHigh = shift == 0 ? Const(0) : context.ShiftRightU32(srcA, Const(32 - shift)); - aHigh = context.BitwiseOr(aHigh, context.ShiftLeft(srcC, Const(shift))); - - if (negateA) - { - // Perform 64-bit negation by doing bitwise not of the value, - // then adding 1 and carrying over from low to high. - aLow = context.BitwiseNot(aLow); - aHigh = context.BitwiseNot(aHigh); - - aLow = AddWithCarry(context, aLow, Const(1), out Operand aLowCOut); - aHigh = context.IAdd(aHigh, aLowCOut); - } - - Operand res = context.IAdd(aHigh, srcB); - - context.Copy(GetDest(rd), res); - - // TODO: CC, X. - } - - public static void EmitXmad( - EmitterContext context, - XmadCop2 mode, - Operand srcA, - Operand srcB, - Operand srcC, - int rd, - bool signedA, - bool signedB, - bool highA, - bool highB, - bool productShiftLeft, - bool merge, - bool extended, - bool writeCC) - { - XmadCop modeConv; - switch (mode) - { - case XmadCop2.Cfull: - modeConv = XmadCop.Cfull; - break; - case XmadCop2.Clo: - modeConv = XmadCop.Clo; - break; - case XmadCop2.Chi: - modeConv = XmadCop.Chi; - break; - case XmadCop2.Csfu: - modeConv = XmadCop.Csfu; - break; - default: - context.Config.GpuAccessor.Log($"Invalid XMAD mode \"{mode}\"."); - return; - } - - EmitXmad(context, modeConv, srcA, srcB, srcC, rd, signedA, signedB, highA, highB, productShiftLeft, merge, extended, writeCC); - } - - public static void EmitXmad( - EmitterContext context, - XmadCop mode, - Operand srcA, - Operand srcB, - Operand srcC, - int rd, - bool signedA, - bool signedB, - bool highA, - bool highB, - bool productShiftLeft, - bool merge, - bool extended, - bool writeCC) - { - var srcBUnmodified = srcB; - - Operand Extend16To32(Operand src, bool high, bool signed) - { - if (signed && high) - { - return context.ShiftRightS32(src, Const(16)); - } - else if (signed) - { - return context.BitfieldExtractS32(src, Const(0), Const(16)); - } - else if (high) - { - return context.ShiftRightU32(src, Const(16)); - } - else - { - return context.BitwiseAnd(src, Const(0xffff)); - } - } - - srcA = Extend16To32(srcA, highA, signedA); - srcB = Extend16To32(srcB, highB, signedB); - - Operand res = context.IMultiply(srcA, srcB); - - if (productShiftLeft) - { - res = context.ShiftLeft(res, Const(16)); - } - - switch (mode) - { - case XmadCop.Cfull: - break; - - case XmadCop.Clo: - srcC = Extend16To32(srcC, high: false, signed: false); - break; - case XmadCop.Chi: - srcC = Extend16To32(srcC, high: true, signed: false); - break; - - case XmadCop.Cbcc: - srcC = context.IAdd(srcC, context.ShiftLeft(srcBUnmodified, Const(16))); - break; - - case XmadCop.Csfu: - Operand signAdjustA = context.ShiftLeft(context.ShiftRightU32(srcA, Const(31)), Const(16)); - Operand signAdjustB = context.ShiftLeft(context.ShiftRightU32(srcB, Const(31)), Const(16)); - - srcC = context.ISubtract(srcC, context.IAdd(signAdjustA, signAdjustB)); - break; - - default: - context.Config.GpuAccessor.Log($"Invalid XMAD mode \"{mode}\"."); - return; - } - - Operand product = res; - - if (extended) - { - // Add with carry. - res = context.IAdd(res, context.BitwiseAnd(GetCF(), Const(1))); - } - else - { - // Add (no carry in). - res = context.IAdd(res, srcC); - } - - SetIaddFlags(context, res, product, srcC, writeCC, extended); - - if (merge) - { - res = context.BitwiseAnd(res, Const(0xffff)); - res = context.BitwiseOr(res, context.ShiftLeft(srcBUnmodified, Const(16))); - } - - context.Copy(GetDest(rd), res); - } - - private static void SetIaddFlags(EmitterContext context, Operand res, Operand srcA, Operand srcB, bool setCC, bool extended) - { - if (!setCC) - { - return; - } - - if (extended) - { - // C = (d == a && CIn) || d < a - Operand tempC0 = context.ICompareEqual(res, srcA); - Operand tempC1 = context.ICompareLessUnsigned(res, srcA); - - tempC0 = context.BitwiseAnd(tempC0, GetCF()); - - context.Copy(GetCF(), context.BitwiseOr(tempC0, tempC1)); - } - else - { - // C = d < a - context.Copy(GetCF(), context.ICompareLessUnsigned(res, srcA)); - } - - // V = (d ^ a) & ~(a ^ b) < 0 - Operand tempV0 = context.BitwiseExclusiveOr(res, srcA); - Operand tempV1 = context.BitwiseExclusiveOr(srcA, srcB); - - tempV1 = context.BitwiseNot(tempV1); - - Operand tempV = context.BitwiseAnd(tempV0, tempV1); - - context.Copy(GetVF(), context.ICompareLess(tempV, Const(0))); - - SetZnFlags(context, res, setCC: true, extended: extended); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerComparison.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerComparison.cs deleted file mode 100644 index dcdb189f..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerComparison.cs +++ /dev/null @@ -1,310 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; -using System; - -using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - public static void IcmpR(EmitterContext context) - { - InstIcmpR op = context.GetOp<InstIcmpR>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcB); - var srcC = GetSrcReg(context, op.SrcC); - - EmitIcmp(context, op.IComp, srcA, srcB, srcC, op.Dest, op.Signed); - } - - public static void IcmpI(EmitterContext context) - { - InstIcmpI op = context.GetOp<InstIcmpI>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); - var srcC = GetSrcReg(context, op.SrcC); - - EmitIcmp(context, op.IComp, srcA, srcB, srcC, op.Dest, op.Signed); - } - - public static void IcmpC(EmitterContext context) - { - InstIcmpC op = context.GetOp<InstIcmpC>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - var srcC = GetSrcReg(context, op.SrcC); - - EmitIcmp(context, op.IComp, srcA, srcB, srcC, op.Dest, op.Signed); - } - - public static void IcmpRc(EmitterContext context) - { - InstIcmpRc op = context.GetOp<InstIcmpRc>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcC); - var srcC = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - - EmitIcmp(context, op.IComp, srcA, srcB, srcC, op.Dest, op.Signed); - } - - public static void IsetR(EmitterContext context) - { - InstIsetR op = context.GetOp<InstIsetR>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcB); - - EmitIset(context, op.IComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.Dest, op.BVal, op.Signed, op.X, op.WriteCC); - } - - public static void IsetI(EmitterContext context) - { - InstIsetI op = context.GetOp<InstIsetI>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); - - EmitIset(context, op.IComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.Dest, op.BVal, op.Signed, op.X, op.WriteCC); - } - - public static void IsetC(EmitterContext context) - { - InstIsetC op = context.GetOp<InstIsetC>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - - EmitIset(context, op.IComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.Dest, op.BVal, op.Signed, op.X, op.WriteCC); - } - - public static void IsetpR(EmitterContext context) - { - InstIsetpR op = context.GetOp<InstIsetpR>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcB); - - EmitIsetp(context, op.IComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.DestPred, op.DestPredInv, op.Signed, op.X); - } - - public static void IsetpI(EmitterContext context) - { - InstIsetpI op = context.GetOp<InstIsetpI>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); - - EmitIsetp(context, op.IComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.DestPred, op.DestPredInv, op.Signed, op.X); - } - - public static void IsetpC(EmitterContext context) - { - InstIsetpC op = context.GetOp<InstIsetpC>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - - EmitIsetp(context, op.IComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.DestPred, op.DestPredInv, op.Signed, op.X); - } - - private static void EmitIcmp( - EmitterContext context, - IComp cmpOp, - Operand srcA, - Operand srcB, - Operand srcC, - int rd, - bool isSigned) - { - Operand cmpRes = GetIntComparison(context, cmpOp, srcC, Const(0), isSigned); - - Operand res = context.ConditionalSelect(cmpRes, srcA, srcB); - - context.Copy(GetDest(rd), res); - } - - private static void EmitIset( - EmitterContext context, - IComp cmpOp, - BoolOp logicOp, - Operand srcA, - Operand srcB, - int srcPred, - bool srcPredInv, - int rd, - bool boolFloat, - bool isSigned, - bool extended, - bool writeCC) - { - Operand res = GetIntComparison(context, cmpOp, srcA, srcB, isSigned, extended); - Operand pred = GetPredicate(context, srcPred, srcPredInv); - - res = GetPredLogicalOp(context, logicOp, res, pred); - - Operand dest = GetDest(rd); - - if (boolFloat) - { - res = context.ConditionalSelect(res, ConstF(1), Const(0)); - - context.Copy(dest, res); - - SetFPZnFlags(context, res, writeCC); - } - else - { - context.Copy(dest, res); - - SetZnFlags(context, res, writeCC, extended); - } - } - - private static void EmitIsetp( - EmitterContext context, - IComp cmpOp, - BoolOp logicOp, - Operand srcA, - Operand srcB, - int srcPred, - bool srcPredInv, - int destPred, - int destPredInv, - bool isSigned, - bool extended) - { - Operand p0Res = GetIntComparison(context, cmpOp, srcA, srcB, isSigned, extended); - Operand p1Res = context.BitwiseNot(p0Res); - Operand pred = GetPredicate(context, srcPred, srcPredInv); - - p0Res = GetPredLogicalOp(context, logicOp, p0Res, pred); - p1Res = GetPredLogicalOp(context, logicOp, p1Res, pred); - - context.Copy(Register(destPred, RegisterType.Predicate), p0Res); - context.Copy(Register(destPredInv, RegisterType.Predicate), p1Res); - } - - private static Operand GetIntComparison( - EmitterContext context, - IComp cond, - Operand srcA, - Operand srcB, - bool isSigned, - bool extended) - { - return extended - ? GetIntComparisonExtended(context, cond, srcA, srcB, isSigned) - : GetIntComparison(context, cond, srcA, srcB, isSigned); - } - - private static Operand GetIntComparisonExtended(EmitterContext context, IComp cond, Operand srcA, Operand srcB, bool isSigned) - { - Operand res; - - if (cond == IComp.T) - { - res = Const(IrConsts.True); - } - else if (cond == IComp.F) - { - res = Const(IrConsts.False); - } - else - { - res = context.ISubtract(srcA, srcB); - res = context.IAdd(res, context.BitwiseNot(GetCF())); - - switch (cond) - { - case IComp.Eq: // r = xh == yh && xl == yl - res = context.BitwiseAnd(context.ICompareEqual(srcA, srcB), GetZF()); - break; - case IComp.Lt: // r = xh < yh || (xh == yh && xl < yl) - Operand notC = context.BitwiseNot(GetCF()); - Operand prevLt = context.BitwiseAnd(context.ICompareEqual(srcA, srcB), notC); - res = isSigned - ? context.BitwiseOr(context.ICompareLess(srcA, srcB), prevLt) - : context.BitwiseOr(context.ICompareLessUnsigned(srcA, srcB), prevLt); - break; - case IComp.Le: // r = xh < yh || (xh == yh && xl <= yl) - Operand zOrNotC = context.BitwiseOr(GetZF(), context.BitwiseNot(GetCF())); - Operand prevLe = context.BitwiseAnd(context.ICompareEqual(srcA, srcB), zOrNotC); - res = isSigned - ? context.BitwiseOr(context.ICompareLess(srcA, srcB), prevLe) - : context.BitwiseOr(context.ICompareLessUnsigned(srcA, srcB), prevLe); - break; - case IComp.Gt: // r = xh > yh || (xh == yh && xl > yl) - Operand notZAndC = context.BitwiseAnd(context.BitwiseNot(GetZF()), GetCF()); - Operand prevGt = context.BitwiseAnd(context.ICompareEqual(srcA, srcB), notZAndC); - res = isSigned - ? context.BitwiseOr(context.ICompareGreater(srcA, srcB), prevGt) - : context.BitwiseOr(context.ICompareGreaterUnsigned(srcA, srcB), prevGt); - break; - case IComp.Ge: // r = xh > yh || (xh == yh && xl >= yl) - Operand prevGe = context.BitwiseAnd(context.ICompareEqual(srcA, srcB), GetCF()); - res = isSigned - ? context.BitwiseOr(context.ICompareGreater(srcA, srcB), prevGe) - : context.BitwiseOr(context.ICompareGreaterUnsigned(srcA, srcB), prevGe); - break; - case IComp.Ne: // r = xh != yh || xl != yl - res = context.BitwiseOr(context.ICompareNotEqual(srcA, srcB), context.BitwiseNot(GetZF())); - break; - default: - throw new ArgumentException($"Unexpected condition \"{cond}\"."); - } - } - - return res; - } - - private static Operand GetIntComparison(EmitterContext context, IComp cond, Operand srcA, Operand srcB, bool isSigned) - { - Operand res; - - if (cond == IComp.T) - { - res = Const(IrConsts.True); - } - else if (cond == IComp.F) - { - res = Const(IrConsts.False); - } - else - { - var inst = cond switch - { - IComp.Lt => Instruction.CompareLessU32, - IComp.Eq => Instruction.CompareEqual, - IComp.Le => Instruction.CompareLessOrEqualU32, - IComp.Gt => Instruction.CompareGreaterU32, - IComp.Ne => Instruction.CompareNotEqual, - IComp.Ge => Instruction.CompareGreaterOrEqualU32, - _ => throw new InvalidOperationException($"Unexpected condition \"{cond}\".") - }; - - if (isSigned) - { - switch (cond) - { - case IComp.Lt: inst = Instruction.CompareLess; break; - case IComp.Le: inst = Instruction.CompareLessOrEqual; break; - case IComp.Gt: inst = Instruction.CompareGreater; break; - case IComp.Ge: inst = Instruction.CompareGreaterOrEqual; break; - } - } - - res = context.Add(inst, Local(), srcA, srcB); - } - - return res; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerLogical.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerLogical.cs deleted file mode 100644 index 1f3f66ae..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerLogical.cs +++ /dev/null @@ -1,167 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; - -using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - private const int PT = RegisterConsts.PredicateTrueIndex; - - public static void LopR(EmitterContext context) - { - InstLopR op = context.GetOp<InstLopR>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcB); - - EmitLop(context, op.Lop, op.PredicateOp, srcA, srcB, op.Dest, op.DestPred, op.NegA, op.NegB, op.X, op.WriteCC); - } - - public static void LopI(EmitterContext context) - { - InstLopI op = context.GetOp<InstLopI>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); - - EmitLop(context, op.LogicOp, op.PredicateOp, srcA, srcB, op.Dest, op.DestPred, op.NegA, op.NegB, op.X, op.WriteCC); - } - - public static void LopC(EmitterContext context) - { - InstLopC op = context.GetOp<InstLopC>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - - EmitLop(context, op.LogicOp, op.PredicateOp, srcA, srcB, op.Dest, op.DestPred, op.NegA, op.NegB, op.X, op.WriteCC); - } - - public static void Lop32i(EmitterContext context) - { - InstLop32i op = context.GetOp<InstLop32i>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, op.Imm32); - - EmitLop(context, op.LogicOp, PredicateOp.F, srcA, srcB, op.Dest, PT, op.NegA, op.NegB, op.X, op.WriteCC); - } - - public static void Lop3R(EmitterContext context) - { - InstLop3R op = context.GetOp<InstLop3R>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcB); - var srcC = GetSrcReg(context, op.SrcC); - - EmitLop3(context, op.Imm, op.PredicateOp, srcA, srcB, srcC, op.Dest, op.DestPred, op.X, op.WriteCC); - } - - public static void Lop3I(EmitterContext context) - { - InstLop3I op = context.GetOp<InstLop3I>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); - var srcC = GetSrcReg(context, op.SrcC); - - EmitLop3(context, op.Imm, PredicateOp.F, srcA, srcB, srcC, op.Dest, PT, false, op.WriteCC); - } - - public static void Lop3C(EmitterContext context) - { - InstLop3C op = context.GetOp<InstLop3C>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - var srcC = GetSrcReg(context, op.SrcC); - - EmitLop3(context, op.Imm, PredicateOp.F, srcA, srcB, srcC, op.Dest, PT, false, op.WriteCC); - } - - private static void EmitLop( - EmitterContext context, - LogicOp logicOp, - PredicateOp predOp, - Operand srcA, - Operand srcB, - int rd, - int destPred, - bool invertA, - bool invertB, - bool extended, - bool writeCC) - { - srcA = context.BitwiseNot(srcA, invertA); - srcB = context.BitwiseNot(srcB, invertB); - - Operand res = logicOp switch - { - LogicOp.And => res = context.BitwiseAnd(srcA, srcB), - LogicOp.Or => res = context.BitwiseOr(srcA, srcB), - LogicOp.Xor => res = context.BitwiseExclusiveOr(srcA, srcB), - _ => srcB - }; - - EmitLopPredWrite(context, res, predOp, destPred); - - context.Copy(GetDest(rd), res); - - SetZnFlags(context, res, writeCC, extended); - } - - private static void EmitLop3( - EmitterContext context, - int truthTable, - PredicateOp predOp, - Operand srcA, - Operand srcB, - Operand srcC, - int rd, - int destPred, - bool extended, - bool writeCC) - { - Operand res = Lop3Expression.GetFromTruthTable(context, srcA, srcB, srcC, truthTable); - - EmitLopPredWrite(context, res, predOp, destPred); - - context.Copy(GetDest(rd), res); - - SetZnFlags(context, res, writeCC, extended); - } - - private static void EmitLopPredWrite(EmitterContext context, Operand result, PredicateOp predOp, int pred) - { - if (pred != RegisterConsts.PredicateTrueIndex) - { - Operand pRes; - - if (predOp == PredicateOp.F) - { - pRes = Const(IrConsts.False); - } - else if (predOp == PredicateOp.T) - { - pRes = Const(IrConsts.True); - } - else if (predOp == PredicateOp.Z) - { - pRes = context.ICompareEqual(result, Const(0)); - } - else /* if (predOp == Pop.Nz) */ - { - pRes = context.ICompareNotEqual(result, Const(0)); - } - - context.Copy(Register(pred, RegisterType.Predicate), pRes); - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerMinMax.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerMinMax.cs deleted file mode 100644 index 73930ed1..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerMinMax.cs +++ /dev/null @@ -1,71 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; - -using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - public static void ImnmxR(EmitterContext context) - { - InstImnmxR op = context.GetOp<InstImnmxR>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcB); - var srcPred = GetPredicate(context, op.SrcPred, op.SrcPredInv); - - EmitImnmx(context, srcA, srcB, srcPred, op.Dest, op.Signed, op.WriteCC); - } - - public static void ImnmxI(EmitterContext context) - { - InstImnmxI op = context.GetOp<InstImnmxI>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); - var srcPred = GetPredicate(context, op.SrcPred, op.SrcPredInv); - - EmitImnmx(context, srcA, srcB, srcPred, op.Dest, op.Signed, op.WriteCC); - } - - public static void ImnmxC(EmitterContext context) - { - InstImnmxC op = context.GetOp<InstImnmxC>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - var srcPred = GetPredicate(context, op.SrcPred, op.SrcPredInv); - - EmitImnmx(context, srcA, srcB, srcPred, op.Dest, op.Signed, op.WriteCC); - } - - private static void EmitImnmx( - EmitterContext context, - Operand srcA, - Operand srcB, - Operand srcPred, - int rd, - bool isSignedInt, - bool writeCC) - { - Operand resMin = isSignedInt - ? context.IMinimumS32(srcA, srcB) - : context.IMinimumU32(srcA, srcB); - - Operand resMax = isSignedInt - ? context.IMaximumS32(srcA, srcB) - : context.IMaximumU32(srcA, srcB); - - Operand res = context.ConditionalSelect(srcPred, resMin, resMax); - - context.Copy(GetDest(rd), res); - - SetZnFlags(context, res, writeCC); - - // TODO: X flags. - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs deleted file mode 100644 index c73c6b2a..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs +++ /dev/null @@ -1,541 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; - -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - private enum MemoryRegion - { - Local, - Shared - } - - public static void Atom(EmitterContext context) - { - InstAtom op = context.GetOp<InstAtom>(); - - int sOffset = (op.Imm20 << 12) >> 12; - - (Operand addrLow, Operand addrHigh) = Get40BitsAddress(context, new Register(op.SrcA, RegisterType.Gpr), op.E, sOffset); - - Operand value = GetSrcReg(context, op.SrcB); - - Operand res = EmitAtomicOp(context, StorageKind.GlobalMemory, op.Op, op.Size, addrLow, addrHigh, value); - - context.Copy(GetDest(op.Dest), res); - } - - public static void Atoms(EmitterContext context) - { - InstAtoms op = context.GetOp<InstAtoms>(); - - Operand offset = context.ShiftRightU32(GetSrcReg(context, op.SrcA), Const(2)); - - int sOffset = (op.Imm22 << 10) >> 10; - - offset = context.IAdd(offset, Const(sOffset)); - - Operand value = GetSrcReg(context, op.SrcB); - - AtomSize size = op.AtomsSize switch - { - AtomsSize.S32 => AtomSize.S32, - AtomsSize.U64 => AtomSize.U64, - AtomsSize.S64 => AtomSize.S64, - _ => AtomSize.U32 - }; - - Operand res = EmitAtomicOp(context, StorageKind.SharedMemory, op.AtomOp, size, offset, Const(0), value); - - context.Copy(GetDest(op.Dest), res); - } - - public static void Ldc(EmitterContext context) - { - InstLdc op = context.GetOp<InstLdc>(); - - if (op.LsSize > LsSize2.B64) - { - context.Config.GpuAccessor.Log($"Invalid LDC size: {op.LsSize}."); - return; - } - - bool isSmallInt = op.LsSize < LsSize2.B32; - - int count = op.LsSize == LsSize2.B64 ? 2 : 1; - - Operand slot = Const(op.CbufSlot); - Operand srcA = GetSrcReg(context, op.SrcA); - - if (op.AddressMode == AddressMode.Is || op.AddressMode == AddressMode.Isl) - { - slot = context.IAdd(slot, context.BitfieldExtractU32(srcA, Const(16), Const(16))); - srcA = context.BitwiseAnd(srcA, Const(0xffff)); - } - - Operand addr = context.IAdd(srcA, Const(Imm16ToSInt(op.CbufOffset))); - Operand wordOffset = context.ShiftRightU32(addr, Const(2)); - Operand bitOffset = GetBitOffset(context, addr); - - for (int index = 0; index < count; index++) - { - Register dest = new Register(op.Dest + index, RegisterType.Gpr); - - if (dest.IsRZ) - { - break; - } - - Operand offset = context.IAdd(wordOffset, Const(index)); - Operand value = context.LoadConstant(slot, offset); - - if (isSmallInt) - { - value = ExtractSmallInt(context, (LsSize)op.LsSize, bitOffset, value); - } - - context.Copy(Register(dest), value); - } - } - - public static void Ldg(EmitterContext context) - { - InstLdg op = context.GetOp<InstLdg>(); - - EmitLdg(context, op.LsSize, op.SrcA, op.Dest, Imm24ToSInt(op.Imm24), op.E); - } - - public static void Ldl(EmitterContext context) - { - InstLdl op = context.GetOp<InstLdl>(); - - EmitLoad(context, MemoryRegion.Local, op.LsSize, GetSrcReg(context, op.SrcA), op.Dest, Imm24ToSInt(op.Imm24)); - } - - public static void Lds(EmitterContext context) - { - InstLds op = context.GetOp<InstLds>(); - - EmitLoad(context, MemoryRegion.Shared, op.LsSize, GetSrcReg(context, op.SrcA), op.Dest, Imm24ToSInt(op.Imm24)); - } - - public static void Red(EmitterContext context) - { - InstRed op = context.GetOp<InstRed>(); - - (Operand addrLow, Operand addrHigh) = Get40BitsAddress(context, new Register(op.SrcA, RegisterType.Gpr), op.E, op.Imm20); - - EmitAtomicOp(context, StorageKind.GlobalMemory, (AtomOp)op.RedOp, op.RedSize, addrLow, addrHigh, GetDest(op.SrcB)); - } - - public static void Stg(EmitterContext context) - { - InstStg op = context.GetOp<InstStg>(); - - EmitStg(context, op.LsSize, op.SrcA, op.Dest, Imm24ToSInt(op.Imm24), op.E); - } - - public static void Stl(EmitterContext context) - { - InstStl op = context.GetOp<InstStl>(); - - EmitStore(context, MemoryRegion.Local, op.LsSize, GetSrcReg(context, op.SrcA), op.Dest, Imm24ToSInt(op.Imm24)); - } - - public static void Sts(EmitterContext context) - { - InstSts op = context.GetOp<InstSts>(); - - EmitStore(context, MemoryRegion.Shared, op.LsSize, GetSrcReg(context, op.SrcA), op.Dest, Imm24ToSInt(op.Imm24)); - } - - private static Operand EmitAtomicOp( - EmitterContext context, - StorageKind storageKind, - AtomOp op, - AtomSize type, - Operand addrLow, - Operand addrHigh, - Operand value) - { - Operand res = Const(0); - - switch (op) - { - case AtomOp.Add: - if (type == AtomSize.S32 || type == AtomSize.U32) - { - res = context.AtomicAdd(storageKind, addrLow, addrHigh, value); - } - else - { - context.Config.GpuAccessor.Log($"Invalid reduction type: {type}."); - } - break; - case AtomOp.And: - if (type == AtomSize.S32 || type == AtomSize.U32) - { - res = context.AtomicAnd(storageKind, addrLow, addrHigh, value); - } - else - { - context.Config.GpuAccessor.Log($"Invalid reduction type: {type}."); - } - break; - case AtomOp.Xor: - if (type == AtomSize.S32 || type == AtomSize.U32) - { - res = context.AtomicXor(storageKind, addrLow, addrHigh, value); - } - else - { - context.Config.GpuAccessor.Log($"Invalid reduction type: {type}."); - } - break; - case AtomOp.Or: - if (type == AtomSize.S32 || type == AtomSize.U32) - { - res = context.AtomicOr(storageKind, addrLow, addrHigh, value); - } - else - { - context.Config.GpuAccessor.Log($"Invalid reduction type: {type}."); - } - break; - case AtomOp.Max: - if (type == AtomSize.S32) - { - res = context.AtomicMaxS32(storageKind, addrLow, addrHigh, value); - } - else if (type == AtomSize.U32) - { - res = context.AtomicMaxU32(storageKind, addrLow, addrHigh, value); - } - else - { - context.Config.GpuAccessor.Log($"Invalid reduction type: {type}."); - } - break; - case AtomOp.Min: - if (type == AtomSize.S32) - { - res = context.AtomicMinS32(storageKind, addrLow, addrHigh, value); - } - else if (type == AtomSize.U32) - { - res = context.AtomicMinU32(storageKind, addrLow, addrHigh, value); - } - else - { - context.Config.GpuAccessor.Log($"Invalid reduction type: {type}."); - } - break; - } - - return res; - } - - private static void EmitLoad( - EmitterContext context, - MemoryRegion region, - LsSize2 size, - Operand srcA, - int rd, - int offset) - { - if (size > LsSize2.B128) - { - context.Config.GpuAccessor.Log($"Invalid load size: {size}."); - return; - } - - bool isSmallInt = size < LsSize2.B32; - - int count = 1; - - switch (size) - { - case LsSize2.B64: count = 2; break; - case LsSize2.B128: count = 4; break; - } - - Operand baseOffset = context.IAdd(srcA, Const(offset)); - Operand wordOffset = context.ShiftRightU32(baseOffset, Const(2)); // Word offset = byte offset / 4 (one word = 4 bytes). - Operand bitOffset = GetBitOffset(context, baseOffset); - - for (int index = 0; index < count; index++) - { - Register dest = new Register(rd + index, RegisterType.Gpr); - - if (dest.IsRZ) - { - break; - } - - Operand elemOffset = context.IAdd(wordOffset, Const(index)); - Operand value = null; - - switch (region) - { - case MemoryRegion.Local: value = context.LoadLocal(elemOffset); break; - case MemoryRegion.Shared: value = context.LoadShared(elemOffset); break; - } - - if (isSmallInt) - { - value = ExtractSmallInt(context, (LsSize)size, bitOffset, value); - } - - context.Copy(Register(dest), value); - } - } - - private static void EmitLdg( - EmitterContext context, - LsSize size, - int ra, - int rd, - int offset, - bool extended) - { - bool isSmallInt = size < LsSize.B32; - - int count = GetVectorCount(size); - - (Operand addrLow, Operand addrHigh) = Get40BitsAddress(context, new Register(ra, RegisterType.Gpr), extended, offset); - - Operand bitOffset = GetBitOffset(context, addrLow); - - for (int index = 0; index < count; index++) - { - Register dest = new Register(rd + index, RegisterType.Gpr); - - if (dest.IsRZ) - { - break; - } - - Operand value = context.LoadGlobal(context.IAdd(addrLow, Const(index * 4)), addrHigh); - - if (isSmallInt) - { - value = ExtractSmallInt(context, size, bitOffset, value); - } - - context.Copy(Register(dest), value); - } - } - - private static void EmitStore( - EmitterContext context, - MemoryRegion region, - LsSize2 size, - Operand srcA, - int rd, - int offset) - { - if (size > LsSize2.B128) - { - context.Config.GpuAccessor.Log($"Invalid store size: {size}."); - return; - } - - bool isSmallInt = size < LsSize2.B32; - - int count = 1; - - switch (size) - { - case LsSize2.B64: count = 2; break; - case LsSize2.B128: count = 4; break; - } - - Operand baseOffset = context.IAdd(srcA, Const(offset)); - Operand wordOffset = context.ShiftRightU32(baseOffset, Const(2)); - Operand bitOffset = GetBitOffset(context, baseOffset); - - for (int index = 0; index < count; index++) - { - bool isRz = rd + index >= RegisterConsts.RegisterZeroIndex; - - Operand value = Register(isRz ? rd : rd + index, RegisterType.Gpr); - Operand elemOffset = context.IAdd(wordOffset, Const(index)); - - if (isSmallInt && region == MemoryRegion.Local) - { - Operand word = context.LoadLocal(elemOffset); - - value = InsertSmallInt(context, (LsSize)size, bitOffset, word, value); - } - - if (region == MemoryRegion.Local) - { - context.StoreLocal(elemOffset, value); - } - else if (region == MemoryRegion.Shared) - { - switch (size) - { - case LsSize2.U8: - case LsSize2.S8: - context.StoreShared8(baseOffset, value); - break; - case LsSize2.U16: - case LsSize2.S16: - context.StoreShared16(baseOffset, value); - break; - default: - context.StoreShared(elemOffset, value); - break; - } - } - } - } - - private static void EmitStg( - EmitterContext context, - LsSize2 size, - int ra, - int rd, - int offset, - bool extended) - { - if (size > LsSize2.B128) - { - context.Config.GpuAccessor.Log($"Invalid store size: {size}."); - return; - } - - int count = GetVectorCount((LsSize)size); - - (Operand addrLow, Operand addrHigh) = Get40BitsAddress(context, new Register(ra, RegisterType.Gpr), extended, offset); - - Operand bitOffset = GetBitOffset(context, addrLow); - - for (int index = 0; index < count; index++) - { - bool isRz = rd + index >= RegisterConsts.RegisterZeroIndex; - - Operand value = Register(isRz ? rd : rd + index, RegisterType.Gpr); - - Operand addrLowOffset = context.IAdd(addrLow, Const(index * 4)); - - if (size == LsSize2.U8 || size == LsSize2.S8) - { - context.StoreGlobal8(addrLowOffset, addrHigh, value); - } - else if (size == LsSize2.U16 || size == LsSize2.S16) - { - context.StoreGlobal16(addrLowOffset, addrHigh, value); - } - else - { - context.StoreGlobal(addrLowOffset, addrHigh, value); - } - } - } - - private static int GetVectorCount(LsSize size) - { - switch (size) - { - case LsSize.B64: - return 2; - case LsSize.B128: - case LsSize.UB128: - return 4; - } - - return 1; - } - - private static (Operand, Operand) Get40BitsAddress( - EmitterContext context, - Register ra, - bool extended, - int offset) - { - Operand addrLow = Register(ra); - Operand addrHigh; - - if (extended && !ra.IsRZ) - { - addrHigh = Register(ra.Index + 1, RegisterType.Gpr); - } - else - { - addrHigh = Const(0); - } - - Operand offs = Const(offset); - - addrLow = context.IAdd(addrLow, offs); - - if (extended) - { - Operand carry = context.ICompareLessUnsigned(addrLow, offs); - - addrHigh = context.IAdd(addrHigh, context.ConditionalSelect(carry, Const(1), Const(0))); - } - - return (addrLow, addrHigh); - } - - private static Operand GetBitOffset(EmitterContext context, Operand baseOffset) - { - // Note: bit offset = (baseOffset & 0b11) * 8. - // Addresses should be always aligned to the integer type, - // so we don't need to take unaligned addresses into account. - return context.ShiftLeft(context.BitwiseAnd(baseOffset, Const(3)), Const(3)); - } - - private static Operand ExtractSmallInt( - EmitterContext context, - LsSize size, - Operand bitOffset, - Operand value) - { - value = context.ShiftRightU32(value, bitOffset); - - switch (size) - { - case LsSize.U8: value = ZeroExtendTo32(context, value, 8); break; - case LsSize.U16: value = ZeroExtendTo32(context, value, 16); break; - case LsSize.S8: value = SignExtendTo32(context, value, 8); break; - case LsSize.S16: value = SignExtendTo32(context, value, 16); break; - } - - return value; - } - - private static Operand InsertSmallInt( - EmitterContext context, - LsSize size, - Operand bitOffset, - Operand word, - Operand value) - { - switch (size) - { - case LsSize.U8: - case LsSize.S8: - value = context.BitwiseAnd(value, Const(0xff)); - value = context.BitfieldInsert(word, value, bitOffset, Const(8)); - break; - - case LsSize.U16: - case LsSize.S16: - value = context.BitwiseAnd(value, Const(0xffff)); - value = context.BitfieldInsert(word, value, bitOffset, Const(16)); - break; - } - - return value; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs deleted file mode 100644 index 9992ac37..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs +++ /dev/null @@ -1,237 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; - -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - public static void MovR(EmitterContext context) - { - InstMovR op = context.GetOp<InstMovR>(); - - context.Copy(GetDest(op.Dest), GetSrcReg(context, op.SrcA)); - } - - public static void MovI(EmitterContext context) - { - InstMovI op = context.GetOp<InstMovI>(); - - context.Copy(GetDest(op.Dest), GetSrcImm(context, op.Imm20)); - } - - public static void MovC(EmitterContext context) - { - InstMovC op = context.GetOp<InstMovC>(); - - context.Copy(GetDest(op.Dest), GetSrcCbuf(context, op.CbufSlot, op.CbufOffset)); - } - - public static void Mov32i(EmitterContext context) - { - InstMov32i op = context.GetOp<InstMov32i>(); - - context.Copy(GetDest(op.Dest), GetSrcImm(context, op.Imm32)); - } - - public static void R2pR(EmitterContext context) - { - InstR2pR op = context.GetOp<InstR2pR>(); - - Operand value = GetSrcReg(context, op.SrcA); - Operand mask = GetSrcReg(context, op.SrcB); - - EmitR2p(context, value, mask, op.ByteSel, op.Ccpr); - } - - public static void R2pI(EmitterContext context) - { - InstR2pI op = context.GetOp<InstR2pI>(); - - Operand value = GetSrcReg(context, op.SrcA); - Operand mask = GetSrcImm(context, Imm20ToSInt(op.Imm20)); - - EmitR2p(context, value, mask, op.ByteSel, op.Ccpr); - } - - public static void R2pC(EmitterContext context) - { - InstR2pC op = context.GetOp<InstR2pC>(); - - Operand value = GetSrcReg(context, op.SrcA); - Operand mask = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - - EmitR2p(context, value, mask, op.ByteSel, op.Ccpr); - } - - public static void S2r(EmitterContext context) - { - InstS2r op = context.GetOp<InstS2r>(); - - Operand src; - - switch (op.SReg) - { - case SReg.LaneId: - src = context.Load(StorageKind.Input, IoVariable.SubgroupLaneId); - break; - - case SReg.InvocationId: - src = context.Load(StorageKind.Input, IoVariable.InvocationId); - break; - - case SReg.YDirection: - src = ConstF(1); // TODO: Use value from Y direction GPU register. - break; - - case SReg.ThreadKill: - src = context.Config.Stage == ShaderStage.Fragment ? context.Load(StorageKind.Input, IoVariable.ThreadKill) : Const(0); - break; - - case SReg.InvocationInfo: - if (context.Config.Stage != ShaderStage.Compute && context.Config.Stage != ShaderStage.Fragment) - { - // Note: Lowest 8-bits seems to contain some primitive index, - // but it seems to be NVIDIA implementation specific as it's only used - // to calculate ISBE offsets, so we can just keep it as zero. - - if (context.Config.Stage == ShaderStage.TessellationControl || - context.Config.Stage == ShaderStage.TessellationEvaluation) - { - src = context.ShiftLeft(context.Load(StorageKind.Input, IoVariable.PatchVertices), Const(16)); - } - else - { - src = Const(context.Config.GpuAccessor.QueryPrimitiveTopology().ToInputVertices() << 16); - } - } - else - { - src = Const(0); - } - break; - - case SReg.TId: - Operand tidX = context.Load(StorageKind.Input, IoVariable.ThreadId, null, Const(0)); - Operand tidY = context.Load(StorageKind.Input, IoVariable.ThreadId, null, Const(1)); - Operand tidZ = context.Load(StorageKind.Input, IoVariable.ThreadId, null, Const(2)); - - tidY = context.ShiftLeft(tidY, Const(16)); - tidZ = context.ShiftLeft(tidZ, Const(26)); - - src = context.BitwiseOr(tidX, context.BitwiseOr(tidY, tidZ)); - break; - - case SReg.TIdX: - src = context.Load(StorageKind.Input, IoVariable.ThreadId, null, Const(0)); - break; - case SReg.TIdY: - src = context.Load(StorageKind.Input, IoVariable.ThreadId, null, Const(1)); - break; - case SReg.TIdZ: - src = context.Load(StorageKind.Input, IoVariable.ThreadId, null, Const(2)); - break; - - case SReg.CtaIdX: - src = context.Load(StorageKind.Input, IoVariable.CtaId, null, Const(0)); - break; - case SReg.CtaIdY: - src = context.Load(StorageKind.Input, IoVariable.CtaId, null, Const(1)); - break; - case SReg.CtaIdZ: - src = context.Load(StorageKind.Input, IoVariable.CtaId, null, Const(2)); - break; - - case SReg.EqMask: - src = context.Load(StorageKind.Input, IoVariable.SubgroupEqMask, null, Const(0)); - break; - case SReg.LtMask: - src = context.Load(StorageKind.Input, IoVariable.SubgroupLtMask, null, Const(0)); - break; - case SReg.LeMask: - src = context.Load(StorageKind.Input, IoVariable.SubgroupLeMask, null, Const(0)); - break; - case SReg.GtMask: - src = context.Load(StorageKind.Input, IoVariable.SubgroupGtMask, null, Const(0)); - break; - case SReg.GeMask: - src = context.Load(StorageKind.Input, IoVariable.SubgroupGeMask, null, Const(0)); - break; - - default: - src = Const(0); - break; - } - - context.Copy(GetDest(op.Dest), src); - } - - public static void SelR(EmitterContext context) - { - InstSelR op = context.GetOp<InstSelR>(); - - Operand srcA = GetSrcReg(context, op.SrcA); - Operand srcB = GetSrcReg(context, op.SrcB); - Operand srcPred = GetPredicate(context, op.SrcPred, op.SrcPredInv); - - EmitSel(context, srcA, srcB, srcPred, op.Dest); - } - - public static void SelI(EmitterContext context) - { - InstSelI op = context.GetOp<InstSelI>(); - - Operand srcA = GetSrcReg(context, op.SrcA); - Operand srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); - Operand srcPred = GetPredicate(context, op.SrcPred, op.SrcPredInv); - - EmitSel(context, srcA, srcB, srcPred, op.Dest); - } - - public static void SelC(EmitterContext context) - { - InstSelC op = context.GetOp<InstSelC>(); - - Operand srcA = GetSrcReg(context, op.SrcA); - Operand srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - Operand srcPred = GetPredicate(context, op.SrcPred, op.SrcPredInv); - - EmitSel(context, srcA, srcB, srcPred, op.Dest); - } - - private static void EmitR2p(EmitterContext context, Operand value, Operand mask, ByteSel byteSel, bool ccpr) - { - Operand Test(Operand value, int bit) - { - return context.ICompareNotEqual(context.BitwiseAnd(value, Const(1 << bit)), Const(0)); - } - - if (ccpr) - { - // TODO: Support Register to condition code flags copy. - context.Config.GpuAccessor.Log("R2P.CC not implemented."); - } - else - { - int shift = (int)byteSel * 8; - - for (int bit = 0; bit < RegisterConsts.PredsCount; bit++) - { - Operand pred = Register(bit, RegisterType.Predicate); - Operand res = context.ConditionalSelect(Test(mask, bit), Test(value, bit + shift), pred); - context.Copy(pred, res); - } - } - } - - private static void EmitSel(EmitterContext context, Operand srcA, Operand srcB, Operand srcPred, int rd) - { - Operand res = context.ConditionalSelect(srcPred, srcA, srcB); - - context.Copy(GetDest(rd), res); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitMultifunction.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitMultifunction.cs deleted file mode 100644 index 1ea7d321..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitMultifunction.cs +++ /dev/null @@ -1,97 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; - -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - public static void RroR(EmitterContext context) - { - InstRroR op = context.GetOp<InstRroR>(); - - EmitRro(context, GetSrcReg(context, op.SrcB), op.Dest, op.AbsB, op.NegB); - } - - public static void RroI(EmitterContext context) - { - InstRroI op = context.GetOp<InstRroI>(); - - EmitRro(context, GetSrcImm(context, Imm20ToFloat(op.Imm20)), op.Dest, op.AbsB, op.NegB); - } - - public static void RroC(EmitterContext context) - { - InstRroC op = context.GetOp<InstRroC>(); - - EmitRro(context, GetSrcCbuf(context, op.CbufSlot, op.CbufOffset), op.Dest, op.AbsB, op.NegB); - } - - public static void Mufu(EmitterContext context) - { - InstMufu op = context.GetOp<InstMufu>(); - - Operand res = context.FPAbsNeg(GetSrcReg(context, op.SrcA), op.AbsA, op.NegA); - - switch (op.MufuOp) - { - case MufuOp.Cos: - res = context.FPCosine(res); - break; - - case MufuOp.Sin: - res = context.FPSine(res); - break; - - case MufuOp.Ex2: - res = context.FPExponentB2(res); - break; - - case MufuOp.Lg2: - res = context.FPLogarithmB2(res); - break; - - case MufuOp.Rcp: - res = context.FPReciprocal(res); - break; - - case MufuOp.Rsq: - res = context.FPReciprocalSquareRoot(res); - break; - - case MufuOp.Rcp64h: - res = context.PackDouble2x32(OperandHelper.Const(0), res); - res = context.UnpackDouble2x32High(context.FPReciprocal(res, Instruction.FP64)); - break; - - case MufuOp.Rsq64h: - res = context.PackDouble2x32(OperandHelper.Const(0), res); - res = context.UnpackDouble2x32High(context.FPReciprocalSquareRoot(res, Instruction.FP64)); - break; - - case MufuOp.Sqrt: - res = context.FPSquareRoot(res); - break; - - default: - context.Config.GpuAccessor.Log($"Invalid MUFU operation \"{op.MufuOp}\"."); - break; - } - - context.Copy(GetDest(op.Dest), context.FPSaturate(res, op.Sat)); - } - - private static void EmitRro(EmitterContext context, Operand srcB, int rd, bool absB, bool negB) - { - // This is the range reduction operator, - // we translate it as a simple move, as it - // should be always followed by a matching - // MUFU instruction. - srcB = context.FPAbsNeg(srcB, absB, negB); - - context.Copy(GetDest(rd), srcB); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitNop.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitNop.cs deleted file mode 100644 index 01144007..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitNop.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.Translation; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - public static void Nop(EmitterContext context) - { - InstNop op = context.GetOp<InstNop>(); - - // No operation. - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitPredicate.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitPredicate.cs deleted file mode 100644 index d605661f..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitPredicate.cs +++ /dev/null @@ -1,54 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; - -using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - public static void Pset(EmitterContext context) - { - InstPset op = context.GetOp<InstPset>(); - - Operand srcA = context.BitwiseNot(Register(op.Src2Pred, RegisterType.Predicate), op.Src2PredInv); - Operand srcB = context.BitwiseNot(Register(op.Src1Pred, RegisterType.Predicate), op.Src1PredInv); - Operand srcC = context.BitwiseNot(Register(op.SrcPred, RegisterType.Predicate), op.SrcPredInv); - - Operand res = GetPredLogicalOp(context, op.BoolOpAB, srcA, srcB); - res = GetPredLogicalOp(context, op.BoolOpC, res, srcC); - - Operand dest = GetDest(op.Dest); - - if (op.BVal) - { - context.Copy(dest, context.ConditionalSelect(res, ConstF(1), Const(0))); - } - else - { - context.Copy(dest, res); - } - } - - public static void Psetp(EmitterContext context) - { - InstPsetp op = context.GetOp<InstPsetp>(); - - Operand srcA = context.BitwiseNot(Register(op.Src2Pred, RegisterType.Predicate), op.Src2PredInv); - Operand srcB = context.BitwiseNot(Register(op.Src1Pred, RegisterType.Predicate), op.Src1PredInv); - - Operand p0Res = GetPredLogicalOp(context, op.BoolOpAB, srcA, srcB); - Operand p1Res = context.BitwiseNot(p0Res); - Operand srcPred = GetPredicate(context, op.SrcPred, op.SrcPredInv); - - p0Res = GetPredLogicalOp(context, op.BoolOpC, p0Res, srcPred); - p1Res = GetPredLogicalOp(context, op.BoolOpC, p1Res, srcPred); - - context.Copy(Register(op.DestPred, RegisterType.Predicate), p0Res); - context.Copy(Register(op.DestPredInv, RegisterType.Predicate), p1Res); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitShift.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitShift.cs deleted file mode 100644 index 2873cad8..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitShift.cs +++ /dev/null @@ -1,249 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; - -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - public static void ShfLR(EmitterContext context) - { - InstShfLR op = context.GetOp<InstShfLR>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcB); - var srcC = GetSrcReg(context, op.SrcC); - - EmitShf(context, op.MaxShift, srcA, srcB, srcC, op.Dest, op.M, left: true, op.WriteCC); - } - - public static void ShfRR(EmitterContext context) - { - InstShfRR op = context.GetOp<InstShfRR>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcB); - var srcC = GetSrcReg(context, op.SrcC); - - EmitShf(context, op.MaxShift, srcA, srcB, srcC, op.Dest, op.M, left: false, op.WriteCC); - } - - public static void ShfLI(EmitterContext context) - { - InstShfLI op = context.GetOp<InstShfLI>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = Const(op.Imm6); - var srcC = GetSrcReg(context, op.SrcC); - - EmitShf(context, op.MaxShift, srcA, srcB, srcC, op.Dest, op.M, left: true, op.WriteCC); - } - - public static void ShfRI(EmitterContext context) - { - InstShfRI op = context.GetOp<InstShfRI>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = Const(op.Imm6); - var srcC = GetSrcReg(context, op.SrcC); - - EmitShf(context, op.MaxShift, srcA, srcB, srcC, op.Dest, op.M, left: false, op.WriteCC); - } - - public static void ShlR(EmitterContext context) - { - InstShlR op = context.GetOp<InstShlR>(); - - EmitShl(context, GetSrcReg(context, op.SrcA), GetSrcReg(context, op.SrcB), op.Dest, op.M); - } - - public static void ShlI(EmitterContext context) - { - InstShlI op = context.GetOp<InstShlI>(); - - EmitShl(context, GetSrcReg(context, op.SrcA), GetSrcImm(context, Imm20ToSInt(op.Imm20)), op.Dest, op.M); - } - - public static void ShlC(EmitterContext context) - { - InstShlC op = context.GetOp<InstShlC>(); - - EmitShl(context, GetSrcReg(context, op.SrcA), GetSrcCbuf(context, op.CbufSlot, op.CbufOffset), op.Dest, op.M); - } - - public static void ShrR(EmitterContext context) - { - InstShrR op = context.GetOp<InstShrR>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcReg(context, op.SrcB); - - EmitShr(context, srcA, srcB, op.Dest, op.M, op.Brev, op.Signed); - } - - public static void ShrI(EmitterContext context) - { - InstShrI op = context.GetOp<InstShrI>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); - - EmitShr(context, srcA, srcB, op.Dest, op.M, op.Brev, op.Signed); - } - - public static void ShrC(EmitterContext context) - { - InstShrC op = context.GetOp<InstShrC>(); - - var srcA = GetSrcReg(context, op.SrcA); - var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); - - EmitShr(context, srcA, srcB, op.Dest, op.M, op.Brev, op.Signed); - } - - private static void EmitShf( - EmitterContext context, - MaxShift maxShift, - Operand srcA, - Operand srcB, - Operand srcC, - int rd, - bool mask, - bool left, - bool writeCC) - { - bool isLongShift = maxShift == MaxShift.U64 || maxShift == MaxShift.S64; - bool signedShift = maxShift == MaxShift.S64; - int maxShiftConst = isLongShift ? 64 : 32; - - if (mask) - { - srcB = context.BitwiseAnd(srcB, Const(maxShiftConst - 1)); - } - - Operand res; - - if (left) - { - // res = (C << B) | (A >> (32 - B)) - res = context.ShiftLeft(srcC, srcB); - res = context.BitwiseOr(res, context.ShiftRightU32(srcA, context.ISubtract(Const(32), srcB))); - - if (isLongShift) - { - // res = B >= 32 ? A << (B - 32) : res - Operand lowerShift = context.ShiftLeft(srcA, context.ISubtract(srcB, Const(32))); - - Operand shiftGreaterThan31 = context.ICompareGreaterOrEqualUnsigned(srcB, Const(32)); - res = context.ConditionalSelect(shiftGreaterThan31, lowerShift, res); - } - } - else - { - // res = (A >> B) | (C << (32 - B)) - res = context.ShiftRightU32(srcA, srcB); - res = context.BitwiseOr(res, context.ShiftLeft(srcC, context.ISubtract(Const(32), srcB))); - - if (isLongShift) - { - // res = B >= 32 ? C >> (B - 32) : res - Operand upperShift = signedShift - ? context.ShiftRightS32(srcC, context.ISubtract(srcB, Const(32))) - : context.ShiftRightU32(srcC, context.ISubtract(srcB, Const(32))); - - Operand shiftGreaterThan31 = context.ICompareGreaterOrEqualUnsigned(srcB, Const(32)); - res = context.ConditionalSelect(shiftGreaterThan31, upperShift, res); - } - } - - if (!mask) - { - // Clamped shift value. - Operand isLessThanMax = context.ICompareLessUnsigned(srcB, Const(maxShiftConst)); - - res = context.ConditionalSelect(isLessThanMax, res, Const(0)); - } - - context.Copy(GetDest(rd), res); - - if (writeCC) - { - InstEmitAluHelper.SetZnFlags(context, res, writeCC); - } - - // TODO: X. - } - - private static void EmitShl(EmitterContext context, Operand srcA, Operand srcB, int rd, bool mask) - { - if (mask) - { - srcB = context.BitwiseAnd(srcB, Const(0x1f)); - } - - Operand res = context.ShiftLeft(srcA, srcB); - - if (!mask) - { - // Clamped shift value. - Operand isLessThan32 = context.ICompareLessUnsigned(srcB, Const(32)); - - res = context.ConditionalSelect(isLessThan32, res, Const(0)); - } - - // TODO: X, CC. - - context.Copy(GetDest(rd), res); - } - - private static void EmitShr( - EmitterContext context, - Operand srcA, - Operand srcB, - int rd, - bool mask, - bool bitReverse, - bool isSigned) - { - if (bitReverse) - { - srcA = context.BitfieldReverse(srcA); - } - - if (mask) - { - srcB = context.BitwiseAnd(srcB, Const(0x1f)); - } - - Operand res = isSigned - ? context.ShiftRightS32(srcA, srcB) - : context.ShiftRightU32(srcA, srcB); - - if (!mask) - { - // Clamped shift value. - Operand resShiftBy32; - - if (isSigned) - { - resShiftBy32 = context.ShiftRightS32(srcA, Const(31)); - } - else - { - resShiftBy32 = Const(0); - } - - Operand isLessThan32 = context.ICompareLessUnsigned(srcB, Const(32)); - - res = context.ConditionalSelect(isLessThan32, res, resShiftBy32); - } - - // TODO: X, CC. - - context.Copy(GetDest(rd), res); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitSurface.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitSurface.cs deleted file mode 100644 index 3d94b893..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitSurface.cs +++ /dev/null @@ -1,796 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; -using System; -using System.Collections.Generic; -using System.Numerics; - -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - public static void SuatomB(EmitterContext context) - { - InstSuatomB op = context.GetOp<InstSuatomB>(); - - EmitSuatom( - context, - op.Dim, - op.Op, - op.Size, - 0, - op.SrcA, - op.SrcB, - op.SrcC, - op.Dest, - op.Ba, - isBindless: true, - compareAndSwap: false); - } - - public static void Suatom(EmitterContext context) - { - InstSuatom op = context.GetOp<InstSuatom>(); - - EmitSuatom( - context, - op.Dim, - op.Op, - op.Size, - op.TidB, - op.SrcA, - op.SrcB, - 0, - op.Dest, - op.Ba, - isBindless: false, - compareAndSwap: false); - } - - public static void SuatomB2(EmitterContext context) - { - InstSuatomB2 op = context.GetOp<InstSuatomB2>(); - - EmitSuatom( - context, - op.Dim, - op.Op, - op.Size, - 0, - op.SrcA, - op.SrcB, - op.SrcC, - op.Dest, - op.Ba, - isBindless: true, - compareAndSwap: false); - } - - public static void SuatomCasB(EmitterContext context) - { - InstSuatomCasB op = context.GetOp<InstSuatomCasB>(); - - EmitSuatom( - context, - op.Dim, - 0, - op.Size, - 0, - op.SrcA, - op.SrcB, - op.SrcC, - op.Dest, - op.Ba, - isBindless: true, - compareAndSwap: true); - } - - public static void SuatomCas(EmitterContext context) - { - InstSuatomCas op = context.GetOp<InstSuatomCas>(); - - EmitSuatom( - context, - op.Dim, - 0, - op.Size, - op.TidB, - op.SrcA, - op.SrcB, - 0, - op.Dest, - op.Ba, - isBindless: false, - compareAndSwap: true); - } - - public static void SuldDB(EmitterContext context) - { - InstSuldDB op = context.GetOp<InstSuldDB>(); - - EmitSuld(context, op.CacheOp, op.Dim, op.Size, 0, 0, op.SrcA, op.Dest, op.SrcC, useComponents: false, op.Ba, isBindless: true); - } - - public static void SuldD(EmitterContext context) - { - InstSuldD op = context.GetOp<InstSuldD>(); - - EmitSuld(context, op.CacheOp, op.Dim, op.Size, op.TidB, 0, op.SrcA, op.Dest, 0, useComponents: false, op.Ba, isBindless: false); - } - - public static void SuldB(EmitterContext context) - { - InstSuldB op = context.GetOp<InstSuldB>(); - - EmitSuld(context, op.CacheOp, op.Dim, 0, 0, op.Rgba, op.SrcA, op.Dest, op.SrcC, useComponents: true, false, isBindless: true); - } - - public static void Suld(EmitterContext context) - { - InstSuld op = context.GetOp<InstSuld>(); - - EmitSuld(context, op.CacheOp, op.Dim, 0, op.TidB, op.Rgba, op.SrcA, op.Dest, 0, useComponents: true, false, isBindless: false); - } - - public static void SuredB(EmitterContext context) - { - InstSuredB op = context.GetOp<InstSuredB>(); - - EmitSured(context, op.Dim, op.Op, op.Size, 0, op.SrcA, op.Dest, op.SrcC, op.Ba, isBindless: true); - } - - public static void Sured(EmitterContext context) - { - InstSured op = context.GetOp<InstSured>(); - - EmitSured(context, op.Dim, op.Op, op.Size, op.TidB, op.SrcA, op.Dest, 0, op.Ba, isBindless: false); - } - - public static void SustDB(EmitterContext context) - { - InstSustDB op = context.GetOp<InstSustDB>(); - - EmitSust(context, op.CacheOp, op.Dim, op.Size, 0, 0, op.SrcA, op.Dest, op.SrcC, useComponents: false, op.Ba, isBindless: true); - } - - public static void SustD(EmitterContext context) - { - InstSustD op = context.GetOp<InstSustD>(); - - EmitSust(context, op.CacheOp, op.Dim, op.Size, op.TidB, 0, op.SrcA, op.Dest, 0, useComponents: false, op.Ba, isBindless: false); - } - - public static void SustB(EmitterContext context) - { - InstSustB op = context.GetOp<InstSustB>(); - - EmitSust(context, op.CacheOp, op.Dim, 0, 0, op.Rgba, op.SrcA, op.Dest, op.SrcC, useComponents: true, false, isBindless: true); - } - - public static void Sust(EmitterContext context) - { - InstSust op = context.GetOp<InstSust>(); - - EmitSust(context, op.CacheOp, op.Dim, 0, op.TidB, op.Rgba, op.SrcA, op.Dest, 0, useComponents: true, false, isBindless: false); - } - - private static void EmitSuatom( - EmitterContext context, - SuDim dimensions, - SuatomOp atomicOp, - SuatomSize size, - int imm, - int srcA, - int srcB, - int srcC, - int dest, - bool byteAddress, - bool isBindless, - bool compareAndSwap) - { - SamplerType type = ConvertSamplerType(dimensions); - - if (type == SamplerType.None) - { - context.Config.GpuAccessor.Log("Invalid image atomic sampler type."); - return; - } - - Operand Ra() - { - if (srcA > RegisterConsts.RegisterZeroIndex) - { - return Const(0); - } - - return context.Copy(Register(srcA++, RegisterType.Gpr)); - } - - Operand Rb() - { - if (srcB > RegisterConsts.RegisterZeroIndex) - { - return Const(0); - } - - return context.Copy(Register(srcB++, RegisterType.Gpr)); - } - - Operand destOperand = dest != RegisterConsts.RegisterZeroIndex ? Register(dest, RegisterType.Gpr) : null; - - List<Operand> sourcesList = new List<Operand>(); - - if (isBindless) - { - sourcesList.Add(context.Copy(GetSrcReg(context, srcC))); - } - - int coordsCount = type.GetDimensions(); - - for (int index = 0; index < coordsCount; index++) - { - sourcesList.Add(Ra()); - } - - if (Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D) - { - sourcesList.Add(Const(0)); - - type &= ~SamplerType.Mask; - type |= SamplerType.Texture2D; - } - - if (type.HasFlag(SamplerType.Array)) - { - sourcesList.Add(Ra()); - - type |= SamplerType.Array; - } - - if (byteAddress) - { - int xIndex = isBindless ? 1 : 0; - - sourcesList[xIndex] = context.ShiftRightS32(sourcesList[xIndex], Const(GetComponentSizeInBytesLog2(size))); - } - - // TODO: FP and 64-bit formats. - TextureFormat format = size == SuatomSize.Sd32 || size == SuatomSize.Sd64 - ? (isBindless ? TextureFormat.Unknown : context.Config.GetTextureFormatAtomic(imm)) - : GetTextureFormat(size); - - if (compareAndSwap) - { - sourcesList.Add(Rb()); - } - - sourcesList.Add(Rb()); - - Operand[] sources = sourcesList.ToArray(); - - TextureFlags flags = compareAndSwap ? TextureFlags.CAS : GetAtomicOpFlags(atomicOp); - - if (isBindless) - { - flags |= TextureFlags.Bindless; - } - - TextureOperation operation = context.CreateTextureOperation( - Instruction.ImageAtomic, - type, - format, - flags, - imm, - 0, - new[] { destOperand }, - sources); - - context.Add(operation); - } - - private static void EmitSuld( - EmitterContext context, - CacheOpLd cacheOp, - SuDim dimensions, - SuSize size, - int imm, - SuRgba componentMask, - int srcA, - int srcB, - int srcC, - bool useComponents, - bool byteAddress, - bool isBindless) - { - context.Config.SetUsedFeature(FeatureFlags.IntegerSampling); - - SamplerType type = ConvertSamplerType(dimensions); - - if (type == SamplerType.None) - { - context.Config.GpuAccessor.Log("Invalid image store sampler type."); - return; - } - - Operand Ra() - { - if (srcA > RegisterConsts.RegisterZeroIndex) - { - return Const(0); - } - - return context.Copy(Register(srcA++, RegisterType.Gpr)); - } - - List<Operand> sourcesList = new List<Operand>(); - - if (isBindless) - { - sourcesList.Add(context.Copy(Register(srcC, RegisterType.Gpr))); - } - - int coordsCount = type.GetDimensions(); - - for (int index = 0; index < coordsCount; index++) - { - sourcesList.Add(Ra()); - } - - if (Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D) - { - sourcesList.Add(Const(0)); - - type &= ~SamplerType.Mask; - type |= SamplerType.Texture2D; - } - - if (type.HasFlag(SamplerType.Array)) - { - sourcesList.Add(Ra()); - } - - Operand[] sources = sourcesList.ToArray(); - - int handle = imm; - - TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None; - - if (cacheOp == CacheOpLd.Cg) - { - flags |= TextureFlags.Coherent; - } - - if (useComponents) - { - Operand[] dests = new Operand[BitOperations.PopCount((uint)componentMask)]; - - int outputIndex = 0; - - for (int i = 0; i < dests.Length; i++) - { - if (srcB + i >= RegisterConsts.RegisterZeroIndex) - { - break; - } - - dests[outputIndex++] = Register(srcB + i, RegisterType.Gpr); - } - - if (outputIndex != dests.Length) - { - Array.Resize(ref dests, outputIndex); - } - - TextureOperation operation = context.CreateTextureOperation( - Instruction.ImageLoad, - type, - flags, - handle, - (int)componentMask, - dests, - sources); - - if (!isBindless) - { - operation.Format = context.Config.GetTextureFormat(handle); - } - - context.Add(operation); - } - else - { - if (byteAddress) - { - int xIndex = isBindless ? 1 : 0; - - sources[xIndex] = context.ShiftRightS32(sources[xIndex], Const(GetComponentSizeInBytesLog2(size))); - } - - int components = GetComponents(size); - int compMask = (1 << components) - 1; - - Operand[] dests = new Operand[components]; - - int outputIndex = 0; - - for (int i = 0; i < dests.Length; i++) - { - if (srcB + i >= RegisterConsts.RegisterZeroIndex) - { - break; - } - - dests[outputIndex++] = Register(srcB + i, RegisterType.Gpr); - } - - if (outputIndex != dests.Length) - { - Array.Resize(ref dests, outputIndex); - } - - TextureOperation operation = context.CreateTextureOperation( - Instruction.ImageLoad, - type, - GetTextureFormat(size), - flags, - handle, - compMask, - dests, - sources); - - context.Add(operation); - - switch (size) - { - case SuSize.U8: context.Copy(dests[0], ZeroExtendTo32(context, dests[0], 8)); break; - case SuSize.U16: context.Copy(dests[0], ZeroExtendTo32(context, dests[0], 16)); break; - case SuSize.S8: context.Copy(dests[0], SignExtendTo32(context, dests[0], 8)); break; - case SuSize.S16: context.Copy(dests[0], SignExtendTo32(context, dests[0], 16)); break; - } - } - } - - private static void EmitSured( - EmitterContext context, - SuDim dimensions, - RedOp atomicOp, - SuatomSize size, - int imm, - int srcA, - int srcB, - int srcC, - bool byteAddress, - bool isBindless) - { - SamplerType type = ConvertSamplerType(dimensions); - - if (type == SamplerType.None) - { - context.Config.GpuAccessor.Log("Invalid image reduction sampler type."); - return; - } - - Operand Ra() - { - if (srcA > RegisterConsts.RegisterZeroIndex) - { - return Const(0); - } - - return context.Copy(Register(srcA++, RegisterType.Gpr)); - } - - Operand Rb() - { - if (srcB > RegisterConsts.RegisterZeroIndex) - { - return Const(0); - } - - return context.Copy(Register(srcB++, RegisterType.Gpr)); - } - - List<Operand> sourcesList = new List<Operand>(); - - if (isBindless) - { - sourcesList.Add(context.Copy(GetSrcReg(context, srcC))); - } - - int coordsCount = type.GetDimensions(); - - for (int index = 0; index < coordsCount; index++) - { - sourcesList.Add(Ra()); - } - - if (Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D) - { - sourcesList.Add(Const(0)); - - type &= ~SamplerType.Mask; - type |= SamplerType.Texture2D; - } - - if (type.HasFlag(SamplerType.Array)) - { - sourcesList.Add(Ra()); - - type |= SamplerType.Array; - } - - if (byteAddress) - { - int xIndex = isBindless ? 1 : 0; - - sourcesList[xIndex] = context.ShiftRightS32(sourcesList[xIndex], Const(GetComponentSizeInBytesLog2(size))); - } - - // TODO: FP and 64-bit formats. - TextureFormat format = size == SuatomSize.Sd32 || size == SuatomSize.Sd64 - ? (isBindless ? TextureFormat.Unknown : context.Config.GetTextureFormatAtomic(imm)) - : GetTextureFormat(size); - - sourcesList.Add(Rb()); - - Operand[] sources = sourcesList.ToArray(); - - TextureFlags flags = GetAtomicOpFlags((SuatomOp)atomicOp); - - if (isBindless) - { - flags |= TextureFlags.Bindless; - } - - TextureOperation operation = context.CreateTextureOperation( - Instruction.ImageAtomic, - type, - format, - flags, - imm, - 0, - null, - sources); - - context.Add(operation); - } - - private static void EmitSust( - EmitterContext context, - CacheOpSt cacheOp, - SuDim dimensions, - SuSize size, - int imm, - SuRgba componentMask, - int srcA, - int srcB, - int srcC, - bool useComponents, - bool byteAddress, - bool isBindless) - { - SamplerType type = ConvertSamplerType(dimensions); - - if (type == SamplerType.None) - { - context.Config.GpuAccessor.Log("Invalid image store sampler type."); - return; - } - - Operand Ra() - { - if (srcA > RegisterConsts.RegisterZeroIndex) - { - return Const(0); - } - - return context.Copy(Register(srcA++, RegisterType.Gpr)); - } - - Operand Rb() - { - if (srcB > RegisterConsts.RegisterZeroIndex) - { - return Const(0); - } - - return context.Copy(Register(srcB++, RegisterType.Gpr)); - } - - List<Operand> sourcesList = new List<Operand>(); - - if (isBindless) - { - sourcesList.Add(context.Copy(Register(srcC, RegisterType.Gpr))); - } - - int coordsCount = type.GetDimensions(); - - for (int index = 0; index < coordsCount; index++) - { - sourcesList.Add(Ra()); - } - - if (Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D) - { - sourcesList.Add(Const(0)); - - type &= ~SamplerType.Mask; - type |= SamplerType.Texture2D; - } - - if (type.HasFlag(SamplerType.Array)) - { - sourcesList.Add(Ra()); - } - - TextureFormat format = TextureFormat.Unknown; - - if (useComponents) - { - for (int compMask = (int)componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++) - { - if ((compMask & 1) != 0) - { - sourcesList.Add(Rb()); - } - } - - if (!isBindless) - { - format = context.Config.GetTextureFormat(imm); - } - } - else - { - if (byteAddress) - { - int xIndex = isBindless ? 1 : 0; - - sourcesList[xIndex] = context.ShiftRightS32(sourcesList[xIndex], Const(GetComponentSizeInBytesLog2(size))); - } - - int components = GetComponents(size); - - for (int compIndex = 0; compIndex < components; compIndex++) - { - sourcesList.Add(Rb()); - } - - format = GetTextureFormat(size); - } - - Operand[] sources = sourcesList.ToArray(); - - int handle = imm; - - TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None; - - if (cacheOp == CacheOpSt.Cg) - { - flags |= TextureFlags.Coherent; - } - - TextureOperation operation = context.CreateTextureOperation( - Instruction.ImageStore, - type, - format, - flags, - handle, - 0, - null, - sources); - - context.Add(operation); - } - - private static int GetComponentSizeInBytesLog2(SuatomSize size) - { - return size switch - { - SuatomSize.U32 => 2, - SuatomSize.S32 => 2, - SuatomSize.U64 => 3, - SuatomSize.F32FtzRn => 2, - SuatomSize.F16x2FtzRn => 2, - SuatomSize.S64 => 3, - SuatomSize.Sd32 => 2, - SuatomSize.Sd64 => 3, - _ => 2 - }; - } - - private static TextureFormat GetTextureFormat(SuatomSize size) - { - return size switch - { - SuatomSize.U32 => TextureFormat.R32Uint, - SuatomSize.S32 => TextureFormat.R32Sint, - SuatomSize.U64 => TextureFormat.R32G32Uint, - SuatomSize.F32FtzRn => TextureFormat.R32Float, - SuatomSize.F16x2FtzRn => TextureFormat.R16G16Float, - SuatomSize.S64 => TextureFormat.R32G32Uint, - SuatomSize.Sd32 => TextureFormat.R32Uint, - SuatomSize.Sd64 => TextureFormat.R32G32Uint, - _ => TextureFormat.R32Uint - }; - } - - private static TextureFlags GetAtomicOpFlags(SuatomOp op) - { - return op switch - { - SuatomOp.Add => TextureFlags.Add, - SuatomOp.Min => TextureFlags.Minimum, - SuatomOp.Max => TextureFlags.Maximum, - SuatomOp.Inc => TextureFlags.Increment, - SuatomOp.Dec => TextureFlags.Decrement, - SuatomOp.And => TextureFlags.BitwiseAnd, - SuatomOp.Or => TextureFlags.BitwiseOr, - SuatomOp.Xor => TextureFlags.BitwiseXor, - SuatomOp.Exch => TextureFlags.Swap, - _ => TextureFlags.Add - }; - } - - private static int GetComponents(SuSize size) - { - return size switch - { - SuSize.B64 => 2, - SuSize.B128 => 4, - SuSize.UB128 => 4, - _ => 1 - }; - } - - private static int GetComponentSizeInBytesLog2(SuSize size) - { - return size switch - { - SuSize.U8 => 0, - SuSize.S8 => 0, - SuSize.U16 => 1, - SuSize.S16 => 1, - SuSize.B32 => 2, - SuSize.B64 => 3, - SuSize.B128 => 4, - SuSize.UB128 => 4, - _ => 2 - }; - } - - private static TextureFormat GetTextureFormat(SuSize size) - { - return size switch - { - SuSize.U8 => TextureFormat.R8Uint, - SuSize.S8 => TextureFormat.R8Sint, - SuSize.U16 => TextureFormat.R16Uint, - SuSize.S16 => TextureFormat.R16Sint, - SuSize.B32 => TextureFormat.R32Uint, - SuSize.B64 => TextureFormat.R32G32Uint, - SuSize.B128 => TextureFormat.R32G32B32A32Uint, - SuSize.UB128 => TextureFormat.R32G32B32A32Uint, - _ => TextureFormat.R32Uint - }; - } - - private static SamplerType ConvertSamplerType(SuDim target) - { - return target switch - { - SuDim._1d => SamplerType.Texture1D, - SuDim._1dBuffer => SamplerType.TextureBuffer, - SuDim._1dArray => SamplerType.Texture1D | SamplerType.Array, - SuDim._2d => SamplerType.Texture2D, - SuDim._2dArray => SamplerType.Texture2D | SamplerType.Array, - SuDim._3d => SamplerType.Texture3D, - _ => SamplerType.None - }; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs deleted file mode 100644 index caa9a775..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs +++ /dev/null @@ -1,1312 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; -using System; -using System.Collections.Generic; -using System.Numerics; - -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - private static readonly int[,] _maskLut = new int[,] - { - { 0b0001, 0b0010, 0b0100, 0b1000, 0b0011, 0b1001, 0b1010, 0b1100 }, - { 0b0111, 0b1011, 0b1101, 0b1110, 0b1111, 0b0000, 0b0000, 0b0000 } - }; - - public const bool Sample1DAs2D = true; - - private enum TexsType - { - Texs, - Tlds, - Tld4s - } - - public static void Tex(EmitterContext context) - { - InstTex op = context.GetOp<InstTex>(); - - EmitTex(context, TextureFlags.None, op.Dim, op.Lod, op.TidB, op.WMask, op.SrcA, op.SrcB, op.Dest, false, op.Dc, op.Aoffi); - } - - public static void TexB(EmitterContext context) - { - InstTexB op = context.GetOp<InstTexB>(); - - EmitTex(context, TextureFlags.Bindless, op.Dim, op.Lodb, 0, op.WMask, op.SrcA, op.SrcB, op.Dest, false, op.Dc, op.Aoffib); - } - - public static void Texs(EmitterContext context) - { - InstTexs op = context.GetOp<InstTexs>(); - - EmitTexs(context, TexsType.Texs, op.TidB, op.WMask, op.SrcA, op.SrcB, op.Dest, op.Dest2, isF16: false); - } - - public static void TexsF16(EmitterContext context) - { - InstTexs op = context.GetOp<InstTexs>(); - - EmitTexs(context, TexsType.Texs, op.TidB, op.WMask, op.SrcA, op.SrcB, op.Dest, op.Dest2, isF16: true); - } - - public static void Tld(EmitterContext context) - { - InstTld op = context.GetOp<InstTld>(); - - context.Config.SetUsedFeature(FeatureFlags.IntegerSampling); - - var lod = op.Lod ? Lod.Ll : Lod.Lz; - - EmitTex(context, TextureFlags.IntCoords, op.Dim, lod, op.TidB, op.WMask, op.SrcA, op.SrcB, op.Dest, op.Ms, false, op.Toff); - } - - public static void TldB(EmitterContext context) - { - InstTldB op = context.GetOp<InstTldB>(); - - context.Config.SetUsedFeature(FeatureFlags.IntegerSampling); - - var flags = TextureFlags.IntCoords | TextureFlags.Bindless; - var lod = op.Lod ? Lod.Ll : Lod.Lz; - - EmitTex(context, flags, op.Dim, lod, 0, op.WMask, op.SrcA, op.SrcB, op.Dest, op.Ms, false, op.Toff); - } - - public static void Tlds(EmitterContext context) - { - InstTlds op = context.GetOp<InstTlds>(); - - EmitTexs(context, TexsType.Tlds, op.TidB, op.WMask, op.SrcA, op.SrcB, op.Dest, op.Dest2, isF16: false); - } - - public static void TldsF16(EmitterContext context) - { - InstTlds op = context.GetOp<InstTlds>(); - - EmitTexs(context, TexsType.Tlds, op.TidB, op.WMask, op.SrcA, op.SrcB, op.Dest, op.Dest2, isF16: true); - } - - public static void Tld4(EmitterContext context) - { - InstTld4 op = context.GetOp<InstTld4>(); - - EmitTld4(context, op.Dim, op.TexComp, op.TidB, op.WMask, op.SrcA, op.SrcB, op.Dest, op.Toff, op.Dc, isBindless: false); - } - - public static void Tld4B(EmitterContext context) - { - InstTld4B op = context.GetOp<InstTld4B>(); - - EmitTld4(context, op.Dim, op.TexComp, 0, op.WMask, op.SrcA, op.SrcB, op.Dest, op.Toff, op.Dc, isBindless: true); - } - - public static void Tld4s(EmitterContext context) - { - InstTld4s op = context.GetOp<InstTld4s>(); - - EmitTexs(context, TexsType.Tld4s, op.TidB, 4, op.SrcA, op.SrcB, op.Dest, op.Dest2, isF16: false); - } - - public static void Tld4sF16(EmitterContext context) - { - InstTld4s op = context.GetOp<InstTld4s>(); - - EmitTexs(context, TexsType.Tld4s, op.TidB, 4, op.SrcA, op.SrcB, op.Dest, op.Dest2, isF16: true); - } - - public static void Tmml(EmitterContext context) - { - InstTmml op = context.GetOp<InstTmml>(); - - EmitTmml(context, op.Dim, op.TidB, op.WMask, op.SrcA, op.SrcB, op.Dest, isBindless: false); - } - - public static void TmmlB(EmitterContext context) - { - InstTmmlB op = context.GetOp<InstTmmlB>(); - - EmitTmml(context, op.Dim, 0, op.WMask, op.SrcA, op.SrcB, op.Dest, isBindless: true); - } - - public static void Txd(EmitterContext context) - { - InstTxd op = context.GetOp<InstTxd>(); - - EmitTxd(context, op.Dim, op.TidB, op.WMask, op.SrcA, op.SrcB, op.Dest, op.Toff, isBindless: false); - } - - public static void TxdB(EmitterContext context) - { - InstTxdB op = context.GetOp<InstTxdB>(); - - EmitTxd(context, op.Dim, 0, op.WMask, op.SrcA, op.SrcB, op.Dest, op.Toff, isBindless: true); - } - - public static void Txq(EmitterContext context) - { - InstTxq op = context.GetOp<InstTxq>(); - - EmitTxq(context, op.TexQuery, op.TidB, op.WMask, op.SrcA, op.Dest, isBindless: false); - } - - public static void TxqB(EmitterContext context) - { - InstTxqB op = context.GetOp<InstTxqB>(); - - EmitTxq(context, op.TexQuery, 0, op.WMask, op.SrcA, op.Dest, isBindless: true); - } - - private static void EmitTex( - EmitterContext context, - TextureFlags flags, - TexDim dimensions, - Lod lodMode, - int imm, - int componentMask, - int raIndex, - int rbIndex, - int rdIndex, - bool isMultisample, - bool hasDepthCompare, - bool hasOffset) - { - if (rdIndex == RegisterConsts.RegisterZeroIndex) - { - return; - } - - Operand Ra() - { - if (raIndex > RegisterConsts.RegisterZeroIndex) - { - return Const(0); - } - - return context.Copy(Register(raIndex++, RegisterType.Gpr)); - } - - Operand Rb() - { - if (rbIndex > RegisterConsts.RegisterZeroIndex) - { - return Const(0); - } - - return context.Copy(Register(rbIndex++, RegisterType.Gpr)); - } - - SamplerType type = ConvertSamplerType(dimensions); - - bool isArray = type.HasFlag(SamplerType.Array); - bool isBindless = flags.HasFlag(TextureFlags.Bindless); - - Operand arrayIndex = isArray ? Ra() : null; - - List<Operand> sourcesList = new List<Operand>(); - - if (isBindless) - { - sourcesList.Add(Rb()); - } - - bool hasLod = lodMode > Lod.Lz; - - if (type == SamplerType.Texture1D && (flags & ~TextureFlags.Bindless) == TextureFlags.IntCoords && !( - hasLod || - hasDepthCompare || - hasOffset || - isArray || - isMultisample)) - { - // For bindless, we don't have any way to know the texture type, - // so we assume it's texture buffer when the sampler type is 1D, since that's more common. - bool isTypeBuffer = isBindless || context.Config.GpuAccessor.QuerySamplerType(imm) == SamplerType.TextureBuffer; - if (isTypeBuffer) - { - type = SamplerType.TextureBuffer; - } - } - - int coordsCount = type.GetDimensions(); - - for (int index = 0; index < coordsCount; index++) - { - sourcesList.Add(Ra()); - } - - bool is1DTo2D = false; - - if (Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D) - { - sourcesList.Add(ConstF(0)); - - type = SamplerType.Texture2D | (type & SamplerType.Array); - is1DTo2D = true; - } - - if (isArray) - { - sourcesList.Add(arrayIndex); - } - - Operand lodValue = hasLod ? Rb() : ConstF(0); - - Operand packedOffs = hasOffset ? Rb() : null; - - if (hasDepthCompare) - { - sourcesList.Add(Rb()); - - type |= SamplerType.Shadow; - } - - if ((lodMode == Lod.Lz || - lodMode == Lod.Ll || - lodMode == Lod.Lla) && !isMultisample && type != SamplerType.TextureBuffer) - { - sourcesList.Add(lodValue); - - flags |= TextureFlags.LodLevel; - } - - if (hasOffset) - { - for (int index = 0; index < coordsCount; index++) - { - sourcesList.Add(context.BitfieldExtractS32(packedOffs, Const(index * 4), Const(4))); - } - - if (is1DTo2D) - { - sourcesList.Add(Const(0)); - } - - flags |= TextureFlags.Offset; - } - - if (lodMode == Lod.Lb || lodMode == Lod.Lba) - { - sourcesList.Add(lodValue); - - flags |= TextureFlags.LodBias; - } - - if (isMultisample) - { - sourcesList.Add(Rb()); - - type |= SamplerType.Multisample; - } - - Operand[] sources = sourcesList.ToArray(); - Operand[] dests = new Operand[BitOperations.PopCount((uint)componentMask)]; - - int outputIndex = 0; - - for (int i = 0; i < dests.Length; i++) - { - if (rdIndex + i >= RegisterConsts.RegisterZeroIndex) - { - break; - } - - dests[outputIndex++] = Register(rdIndex + i, RegisterType.Gpr); - } - - if (outputIndex != dests.Length) - { - Array.Resize(ref dests, outputIndex); - } - - int handle = !isBindless ? imm : 0; - - TextureOperation operation = context.CreateTextureOperation( - Instruction.TextureSample, - type, - flags, - handle, - componentMask, - dests, - sources); - - context.Add(operation); - } - - private static void EmitTexs( - EmitterContext context, - TexsType texsType, - int imm, - int writeMask, - int srcA, - int srcB, - int dest, - int dest2, - bool isF16) - { - if (dest == RegisterConsts.RegisterZeroIndex && dest2 == RegisterConsts.RegisterZeroIndex) - { - return; - } - - List<Operand> sourcesList = new List<Operand>(); - - Operand Ra() - { - if (srcA > RegisterConsts.RegisterZeroIndex) - { - return Const(0); - } - - return context.Copy(Register(srcA++, RegisterType.Gpr)); - } - - Operand Rb() - { - if (srcB > RegisterConsts.RegisterZeroIndex) - { - return Const(0); - } - - return context.Copy(Register(srcB++, RegisterType.Gpr)); - } - - void AddTextureOffset(int coordsCount, int stride, int size) - { - Operand packedOffs = Rb(); - - for (int index = 0; index < coordsCount; index++) - { - sourcesList.Add(context.BitfieldExtractS32(packedOffs, Const(index * stride), Const(size))); - } - } - - SamplerType type; - TextureFlags flags; - - if (texsType == TexsType.Texs) - { - var texsOp = context.GetOp<InstTexs>(); - - type = ConvertSamplerType(texsOp.Target); - - if (type == SamplerType.None) - { - context.Config.GpuAccessor.Log("Invalid texture sampler type."); - return; - } - - flags = ConvertTextureFlags(texsOp.Target); - - // We don't need to handle 1D -> Buffer conversions here as - // only texture sample with integer coordinates can ever use buffer targets. - - if ((type & SamplerType.Array) != 0) - { - Operand arrayIndex = Ra(); - - sourcesList.Add(Ra()); - sourcesList.Add(Rb()); - - sourcesList.Add(arrayIndex); - - if ((type & SamplerType.Shadow) != 0) - { - sourcesList.Add(Rb()); - } - - if ((flags & TextureFlags.LodLevel) != 0) - { - sourcesList.Add(ConstF(0)); - } - } - else - { - switch (texsOp.Target) - { - case TexsTarget.Texture1DLodZero: - sourcesList.Add(Ra()); - - if (Sample1DAs2D) - { - sourcesList.Add(ConstF(0)); - - type &= ~SamplerType.Mask; - type |= SamplerType.Texture2D; - } - - sourcesList.Add(ConstF(0)); - break; - - case TexsTarget.Texture2D: - sourcesList.Add(Ra()); - sourcesList.Add(Rb()); - break; - - case TexsTarget.Texture2DLodZero: - sourcesList.Add(Ra()); - sourcesList.Add(Rb()); - sourcesList.Add(ConstF(0)); - break; - - case TexsTarget.Texture2DLodLevel: - case TexsTarget.Texture2DDepthCompare: - case TexsTarget.Texture3D: - case TexsTarget.TextureCube: - sourcesList.Add(Ra()); - sourcesList.Add(Ra()); - sourcesList.Add(Rb()); - break; - - case TexsTarget.Texture2DLodZeroDepthCompare: - case TexsTarget.Texture3DLodZero: - sourcesList.Add(Ra()); - sourcesList.Add(Ra()); - sourcesList.Add(Rb()); - sourcesList.Add(ConstF(0)); - break; - - case TexsTarget.Texture2DLodLevelDepthCompare: - case TexsTarget.TextureCubeLodLevel: - sourcesList.Add(Ra()); - sourcesList.Add(Ra()); - sourcesList.Add(Rb()); - sourcesList.Add(Rb()); - break; - } - } - } - else if (texsType == TexsType.Tlds) - { - var tldsOp = context.GetOp<InstTlds>(); - - type = ConvertSamplerType(tldsOp.Target); - - if (type == SamplerType.None) - { - context.Config.GpuAccessor.Log("Invalid texel fetch sampler type."); - return; - } - - context.Config.SetUsedFeature(FeatureFlags.IntegerSampling); - - flags = ConvertTextureFlags(tldsOp.Target) | TextureFlags.IntCoords; - - if (tldsOp.Target == TldsTarget.Texture1DLodZero && - context.Config.GpuAccessor.QuerySamplerType(tldsOp.TidB) == SamplerType.TextureBuffer) - { - type = SamplerType.TextureBuffer; - flags &= ~TextureFlags.LodLevel; - } - - switch (tldsOp.Target) - { - case TldsTarget.Texture1DLodZero: - sourcesList.Add(Ra()); - - if (type != SamplerType.TextureBuffer) - { - if (Sample1DAs2D) - { - sourcesList.Add(ConstF(0)); - - type &= ~SamplerType.Mask; - type |= SamplerType.Texture2D; - } - - sourcesList.Add(ConstF(0)); - } - break; - - case TldsTarget.Texture1DLodLevel: - sourcesList.Add(Ra()); - - if (Sample1DAs2D) - { - sourcesList.Add(ConstF(0)); - - type &= ~SamplerType.Mask; - type |= SamplerType.Texture2D; - } - - sourcesList.Add(Rb()); - break; - - case TldsTarget.Texture2DLodZero: - sourcesList.Add(Ra()); - sourcesList.Add(Rb()); - sourcesList.Add(Const(0)); - break; - - case TldsTarget.Texture2DLodZeroOffset: - sourcesList.Add(Ra()); - sourcesList.Add(Ra()); - sourcesList.Add(Const(0)); - break; - - case TldsTarget.Texture2DLodZeroMultisample: - case TldsTarget.Texture2DLodLevel: - case TldsTarget.Texture2DLodLevelOffset: - sourcesList.Add(Ra()); - sourcesList.Add(Ra()); - sourcesList.Add(Rb()); - break; - - case TldsTarget.Texture3DLodZero: - sourcesList.Add(Ra()); - sourcesList.Add(Ra()); - sourcesList.Add(Rb()); - sourcesList.Add(Const(0)); - break; - - case TldsTarget.Texture2DArrayLodZero: - sourcesList.Add(Rb()); - sourcesList.Add(Rb()); - sourcesList.Add(Ra()); - sourcesList.Add(Const(0)); - break; - } - - if ((flags & TextureFlags.Offset) != 0) - { - AddTextureOffset(type.GetDimensions(), 4, 4); - } - } - else if (texsType == TexsType.Tld4s) - { - var tld4sOp = context.GetOp<InstTld4s>(); - - if (!(tld4sOp.Dc || tld4sOp.Aoffi)) - { - sourcesList.Add(Ra()); - sourcesList.Add(Rb()); - } - else - { - sourcesList.Add(Ra()); - sourcesList.Add(Ra()); - } - - type = SamplerType.Texture2D; - flags = TextureFlags.Gather; - - if (tld4sOp.Dc) - { - sourcesList.Add(Rb()); - - type |= SamplerType.Shadow; - } - - if (tld4sOp.Aoffi) - { - AddTextureOffset(type.GetDimensions(), 8, 6); - - flags |= TextureFlags.Offset; - } - - sourcesList.Add(Const((int)tld4sOp.TexComp)); - } - else - { - throw new ArgumentException($"Invalid TEXS type \"{texsType}\"."); - } - - Operand[] sources = sourcesList.ToArray(); - - Operand[] rd0 = new Operand[2] { ConstF(0), ConstF(0) }; - Operand[] rd1 = new Operand[2] { ConstF(0), ConstF(0) }; - - int handle = imm; - int componentMask = _maskLut[dest2 == RegisterConsts.RegisterZeroIndex ? 0 : 1, writeMask]; - - int componentsCount = BitOperations.PopCount((uint)componentMask); - - Operand[] dests = new Operand[componentsCount]; - - int outputIndex = 0; - - for (int i = 0; i < componentsCount; i++) - { - int high = i >> 1; - int low = i & 1; - - if (isF16) - { - dests[outputIndex++] = high != 0 - ? (rd1[low] = Local()) - : (rd0[low] = Local()); - } - else - { - int rdIndex = high != 0 ? dest2 : dest; - - if (rdIndex < RegisterConsts.RegisterZeroIndex) - { - rdIndex += low; - } - - dests[outputIndex++] = Register(rdIndex, RegisterType.Gpr); - } - } - - if (outputIndex != dests.Length) - { - Array.Resize(ref dests, outputIndex); - } - - TextureOperation operation = context.CreateTextureOperation( - Instruction.TextureSample, - type, - flags, - handle, - componentMask, - dests, - sources); - - context.Add(operation); - - if (isF16) - { - context.Copy(Register(dest, RegisterType.Gpr), context.PackHalf2x16(rd0[0], rd0[1])); - context.Copy(Register(dest2, RegisterType.Gpr), context.PackHalf2x16(rd1[0], rd1[1])); - } - } - - private static void EmitTld4( - EmitterContext context, - TexDim dimensions, - TexComp component, - int imm, - int componentMask, - int srcA, - int srcB, - int dest, - TexOffset offset, - bool hasDepthCompare, - bool isBindless) - { - if (dest == RegisterConsts.RegisterZeroIndex) - { - return; - } - - Operand Ra() - { - if (srcA > RegisterConsts.RegisterZeroIndex) - { - return Const(0); - } - - return context.Copy(Register(srcA++, RegisterType.Gpr)); - } - - Operand Rb() - { - if (srcB > RegisterConsts.RegisterZeroIndex) - { - return Const(0); - } - - return context.Copy(Register(srcB++, RegisterType.Gpr)); - } - - bool isArray = - dimensions == TexDim.Array1d || - dimensions == TexDim.Array2d || - dimensions == TexDim.Array3d || - dimensions == TexDim.ArrayCube; - - Operand arrayIndex = isArray ? Ra() : null; - - List<Operand> sourcesList = new List<Operand>(); - - SamplerType type = ConvertSamplerType(dimensions); - TextureFlags flags = TextureFlags.Gather; - - if (isBindless) - { - sourcesList.Add(Rb()); - - flags |= TextureFlags.Bindless; - } - - int coordsCount = type.GetDimensions(); - - for (int index = 0; index < coordsCount; index++) - { - sourcesList.Add(Ra()); - } - - bool is1DTo2D = Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D; - - if (is1DTo2D) - { - sourcesList.Add(ConstF(0)); - - type = SamplerType.Texture2D | (type & SamplerType.Array); - } - - if (isArray) - { - sourcesList.Add(arrayIndex); - } - - Operand[] packedOffs = new Operand[2]; - - bool hasAnyOffset = offset == TexOffset.Aoffi || offset == TexOffset.Ptp; - - packedOffs[0] = hasAnyOffset ? Rb() : null; - packedOffs[1] = offset == TexOffset.Ptp ? Rb() : null; - - if (hasDepthCompare) - { - sourcesList.Add(Rb()); - - type |= SamplerType.Shadow; - } - - if (hasAnyOffset) - { - int offsetTexelsCount = offset == TexOffset.Ptp ? 4 : 1; - - for (int index = 0; index < coordsCount * offsetTexelsCount; index++) - { - Operand packed = packedOffs[(index >> 2) & 1]; - - sourcesList.Add(context.BitfieldExtractS32(packed, Const((index & 3) * 8), Const(6))); - } - - if (is1DTo2D) - { - for (int index = 0; index < offsetTexelsCount; index++) - { - sourcesList.Add(Const(0)); - } - } - - flags |= offset == TexOffset.Ptp ? TextureFlags.Offsets : TextureFlags.Offset; - } - - sourcesList.Add(Const((int)component)); - - Operand[] sources = sourcesList.ToArray(); - Operand[] dests = new Operand[BitOperations.PopCount((uint)componentMask)]; - - int outputIndex = 0; - - for (int i = 0; i < dests.Length; i++) - { - if (dest + i >= RegisterConsts.RegisterZeroIndex) - { - break; - } - - dests[outputIndex++] = Register(dest + i, RegisterType.Gpr); - } - - if (outputIndex != dests.Length) - { - Array.Resize(ref dests, outputIndex); - } - - int handle = imm; - - TextureOperation operation = context.CreateTextureOperation( - Instruction.TextureSample, - type, - flags, - handle, - componentMask, - dests, - sources); - - context.Add(operation); - } - - private static void EmitTmml( - EmitterContext context, - TexDim dimensions, - int imm, - int componentMask, - int srcA, - int srcB, - int dest, - bool isBindless) - { - if (dest == RegisterConsts.RegisterZeroIndex) - { - return; - } - - Operand Ra() - { - if (srcA > RegisterConsts.RegisterZeroIndex) - { - return Const(0); - } - - return context.Copy(Register(srcA++, RegisterType.Gpr)); - } - - Operand Rb() - { - if (srcB > RegisterConsts.RegisterZeroIndex) - { - return Const(0); - } - - return context.Copy(Register(srcB++, RegisterType.Gpr)); - } - - TextureFlags flags = TextureFlags.None; - - List<Operand> sourcesList = new List<Operand>(); - - if (isBindless) - { - sourcesList.Add(Rb()); - - flags |= TextureFlags.Bindless; - } - - SamplerType type = ConvertSamplerType(dimensions); - - int coordsCount = type.GetDimensions(); - - bool isArray = - dimensions == TexDim.Array1d || - dimensions == TexDim.Array2d || - dimensions == TexDim.Array3d || - dimensions == TexDim.ArrayCube; - - Operand arrayIndex = isArray ? Ra() : null; - - for (int index = 0; index < coordsCount; index++) - { - sourcesList.Add(Ra()); - } - - if (Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D) - { - sourcesList.Add(ConstF(0)); - - type = SamplerType.Texture2D | (type & SamplerType.Array); - } - - if (isArray) - { - sourcesList.Add(arrayIndex); - } - - Operand[] sources = sourcesList.ToArray(); - - Operand GetDest() - { - if (dest >= RegisterConsts.RegisterZeroIndex) - { - return null; - } - - return Register(dest++, RegisterType.Gpr); - } - - int handle = imm; - - for (int compMask = componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++) - { - if ((compMask & 1) != 0) - { - Operand destOperand = GetDest(); - - if (destOperand == null) - { - break; - } - - // Components z and w aren't standard, we return 0 in this case and add a comment. - if (compIndex >= 2) - { - context.Add(new CommentNode("Unsupported component z or w found")); - context.Copy(destOperand, Const(0)); - } - else - { - Operand tempDest = Local(); - - TextureOperation operation = context.CreateTextureOperation( - Instruction.Lod, - type, - flags, - handle, - compIndex ^ 1, // The instruction component order is the inverse of GLSL's. - new[] { tempDest }, - sources); - - context.Add(operation); - - tempDest = context.FPMultiply(tempDest, ConstF(256.0f)); - - Operand fixedPointValue = context.FP32ConvertToS32(tempDest); - - context.Copy(destOperand, fixedPointValue); - } - } - } - } - - private static void EmitTxd( - EmitterContext context, - TexDim dimensions, - int imm, - int componentMask, - int srcA, - int srcB, - int dest, - bool hasOffset, - bool isBindless) - { - if (dest == RegisterConsts.RegisterZeroIndex) - { - return; - } - - Operand Ra() - { - if (srcA > RegisterConsts.RegisterZeroIndex) - { - return Const(0); - } - - return context.Copy(Register(srcA++, RegisterType.Gpr)); - } - - Operand Rb() - { - if (srcB > RegisterConsts.RegisterZeroIndex) - { - return Const(0); - } - - return context.Copy(Register(srcB++, RegisterType.Gpr)); - } - - TextureFlags flags = TextureFlags.Derivatives; - - List<Operand> sourcesList = new List<Operand>(); - - if (isBindless) - { - sourcesList.Add(Ra()); - - flags |= TextureFlags.Bindless; - } - - SamplerType type = ConvertSamplerType(dimensions); - - int coordsCount = type.GetDimensions(); - - for (int index = 0; index < coordsCount; index++) - { - sourcesList.Add(Ra()); - } - - bool is1DTo2D = Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D; - - if (is1DTo2D) - { - sourcesList.Add(ConstF(0)); - - type = SamplerType.Texture2D | (type & SamplerType.Array); - } - - Operand packedParams = Ra(); - - bool isArray = - dimensions == TexDim.Array1d || - dimensions == TexDim.Array2d || - dimensions == TexDim.Array3d || - dimensions == TexDim.ArrayCube; - - if (isArray) - { - sourcesList.Add(context.BitwiseAnd(packedParams, Const(0xffff))); - } - - // Derivatives (X and Y). - for (int dIndex = 0; dIndex < 2 * coordsCount; dIndex++) - { - sourcesList.Add(Rb()); - - if (is1DTo2D) - { - sourcesList.Add(ConstF(0)); - } - } - - if (hasOffset) - { - for (int index = 0; index < coordsCount; index++) - { - sourcesList.Add(context.BitfieldExtractS32(packedParams, Const(16 + index * 4), Const(4))); - } - - if (is1DTo2D) - { - sourcesList.Add(Const(0)); - } - - flags |= TextureFlags.Offset; - } - - Operand[] sources = sourcesList.ToArray(); - Operand[] dests = new Operand[BitOperations.PopCount((uint)componentMask)]; - - int outputIndex = 0; - - for (int i = 0; i < dests.Length; i++) - { - if (dest + i >= RegisterConsts.RegisterZeroIndex) - { - break; - } - - dests[outputIndex++] = Register(dest + i, RegisterType.Gpr); - } - - if (outputIndex != dests.Length) - { - Array.Resize(ref dests, outputIndex); - } - - int handle = imm; - - TextureOperation operation = context.CreateTextureOperation( - Instruction.TextureSample, - type, - flags, - handle, - componentMask, - dests, - sources); - - context.Add(operation); - } - - private static void EmitTxq( - EmitterContext context, - TexQuery query, - int imm, - int componentMask, - int srcA, - int dest, - bool isBindless) - { - if (dest == RegisterConsts.RegisterZeroIndex) - { - return; - } - - context.Config.SetUsedFeature(FeatureFlags.IntegerSampling); - - // TODO: Validate and use query. - Instruction inst = Instruction.TextureSize; - TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None; - - Operand Ra() - { - if (srcA > RegisterConsts.RegisterZeroIndex) - { - return Const(0); - } - - return context.Copy(Register(srcA++, RegisterType.Gpr)); - } - - List<Operand> sourcesList = new List<Operand>(); - - if (isBindless) - { - sourcesList.Add(Ra()); - } - - sourcesList.Add(Ra()); - - Operand[] sources = sourcesList.ToArray(); - - Operand GetDest() - { - if (dest >= RegisterConsts.RegisterZeroIndex) - { - return null; - } - - return Register(dest++, RegisterType.Gpr); - } - - SamplerType type; - - if (isBindless) - { - type = (componentMask & 4) != 0 ? SamplerType.Texture3D : SamplerType.Texture2D; - } - else - { - type = context.Config.GpuAccessor.QuerySamplerType(imm); - } - - for (int compMask = componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++) - { - if ((compMask & 1) != 0) - { - Operand destOperand = GetDest(); - - if (destOperand == null) - { - break; - } - - TextureOperation operation = context.CreateTextureOperation( - inst, - type, - flags, - imm, - compIndex, - new[] { destOperand }, - sources); - - context.Add(operation); - } - } - } - - private static SamplerType ConvertSamplerType(TexDim dimensions) - { - return dimensions switch - { - TexDim._1d => SamplerType.Texture1D, - TexDim.Array1d => SamplerType.Texture1D | SamplerType.Array, - TexDim._2d => SamplerType.Texture2D, - TexDim.Array2d => SamplerType.Texture2D | SamplerType.Array, - TexDim._3d => SamplerType.Texture3D, - TexDim.Array3d => SamplerType.Texture3D | SamplerType.Array, - TexDim.Cube => SamplerType.TextureCube, - TexDim.ArrayCube => SamplerType.TextureCube | SamplerType.Array, - _ => throw new ArgumentException($"Invalid texture dimensions \"{dimensions}\".") - }; - } - - private static SamplerType ConvertSamplerType(TexsTarget type) - { - switch (type) - { - case TexsTarget.Texture1DLodZero: - return SamplerType.Texture1D; - - case TexsTarget.Texture2D: - case TexsTarget.Texture2DLodZero: - case TexsTarget.Texture2DLodLevel: - return SamplerType.Texture2D; - - case TexsTarget.Texture2DDepthCompare: - case TexsTarget.Texture2DLodLevelDepthCompare: - case TexsTarget.Texture2DLodZeroDepthCompare: - return SamplerType.Texture2D | SamplerType.Shadow; - - case TexsTarget.Texture2DArray: - case TexsTarget.Texture2DArrayLodZero: - return SamplerType.Texture2D | SamplerType.Array; - - case TexsTarget.Texture2DArrayLodZeroDepthCompare: - return SamplerType.Texture2D | SamplerType.Array | SamplerType.Shadow; - - case TexsTarget.Texture3D: - case TexsTarget.Texture3DLodZero: - return SamplerType.Texture3D; - - case TexsTarget.TextureCube: - case TexsTarget.TextureCubeLodLevel: - return SamplerType.TextureCube; - } - - return SamplerType.None; - } - - private static SamplerType ConvertSamplerType(TldsTarget type) - { - switch (type) - { - case TldsTarget.Texture1DLodZero: - case TldsTarget.Texture1DLodLevel: - return SamplerType.Texture1D; - - case TldsTarget.Texture2DLodZero: - case TldsTarget.Texture2DLodZeroOffset: - case TldsTarget.Texture2DLodLevel: - case TldsTarget.Texture2DLodLevelOffset: - return SamplerType.Texture2D; - - case TldsTarget.Texture2DLodZeroMultisample: - return SamplerType.Texture2D | SamplerType.Multisample; - - case TldsTarget.Texture3DLodZero: - return SamplerType.Texture3D; - - case TldsTarget.Texture2DArrayLodZero: - return SamplerType.Texture2D | SamplerType.Array; - } - - return SamplerType.None; - } - - private static TextureFlags ConvertTextureFlags(TexsTarget type) - { - switch (type) - { - case TexsTarget.Texture1DLodZero: - case TexsTarget.Texture2DLodZero: - case TexsTarget.Texture2DLodLevel: - case TexsTarget.Texture2DLodLevelDepthCompare: - case TexsTarget.Texture2DLodZeroDepthCompare: - case TexsTarget.Texture2DArrayLodZero: - case TexsTarget.Texture2DArrayLodZeroDepthCompare: - case TexsTarget.Texture3DLodZero: - case TexsTarget.TextureCubeLodLevel: - return TextureFlags.LodLevel; - - case TexsTarget.Texture2D: - case TexsTarget.Texture2DDepthCompare: - case TexsTarget.Texture2DArray: - case TexsTarget.Texture3D: - case TexsTarget.TextureCube: - return TextureFlags.None; - } - - return TextureFlags.None; - } - - private static TextureFlags ConvertTextureFlags(TldsTarget type) - { - switch (type) - { - case TldsTarget.Texture1DLodZero: - case TldsTarget.Texture1DLodLevel: - case TldsTarget.Texture2DLodZero: - case TldsTarget.Texture2DLodLevel: - case TldsTarget.Texture2DLodZeroMultisample: - case TldsTarget.Texture3DLodZero: - case TldsTarget.Texture2DArrayLodZero: - return TextureFlags.LodLevel; - - case TldsTarget.Texture2DLodZeroOffset: - case TldsTarget.Texture2DLodLevelOffset: - return TextureFlags.LodLevel | TextureFlags.Offset; - } - - return TextureFlags.None; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitVideoArithmetic.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitVideoArithmetic.cs deleted file mode 100644 index 2d84c5bd..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitVideoArithmetic.cs +++ /dev/null @@ -1,118 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; - -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - public static void Vmad(EmitterContext context) - { - InstVmad op = context.GetOp<InstVmad>(); - - bool aSigned = (op.ASelect & VectorSelect.S8B0) != 0; - bool bSigned = (op.BSelect & VectorSelect.S8B0) != 0; - - Operand srcA = InstEmitAluHelper.Extend(context, GetSrcReg(context, op.SrcA), op.ASelect); - Operand srcC = context.INegate(GetSrcReg(context, op.SrcC), op.AvgMode == AvgMode.NegB); - Operand srcB; - - if (op.BVideo) - { - srcB = InstEmitAluHelper.Extend(context, GetSrcReg(context, op.SrcB), op.BSelect); - } - else - { - int imm = op.Imm16; - - if (bSigned) - { - imm = (imm << 16) >> 16; - } - - srcB = Const(imm); - } - - Operand productLow = context.IMultiply(srcA, srcB); - Operand productHigh; - - if (aSigned == bSigned) - { - productHigh = aSigned - ? context.MultiplyHighS32(srcA, srcB) - : context.MultiplyHighU32(srcA, srcB); - } - else - { - Operand temp = aSigned - ? context.IMultiply(srcB, context.ShiftRightS32(srcA, Const(31))) - : context.IMultiply(srcA, context.ShiftRightS32(srcB, Const(31))); - - productHigh = context.IAdd(temp, context.MultiplyHighU32(srcA, srcB)); - } - - if (op.AvgMode == AvgMode.NegA) - { - (productLow, productHigh) = InstEmitAluHelper.NegateLong(context, productLow, productHigh); - } - - Operand resLow = InstEmitAluHelper.AddWithCarry(context, productLow, srcC, out Operand sumCarry); - Operand resHigh = context.IAdd(productHigh, sumCarry); - - if (op.AvgMode == AvgMode.PlusOne) - { - resLow = InstEmitAluHelper.AddWithCarry(context, resLow, Const(1), out Operand poCarry); - resHigh = context.IAdd(resHigh, poCarry); - } - - bool resSigned = op.ASelect == VectorSelect.S32 || - op.BSelect == VectorSelect.S32 || - op.AvgMode == AvgMode.NegB || - op.AvgMode == AvgMode.NegA; - - int shift = op.VideoScale switch - { - VideoScale.Shr7 => 7, - VideoScale.Shr15 => 15, - _ => 0 - }; - - if (shift != 0) - { - // Low = (Low >> Shift) | (High << (32 - Shift)) - // High >>= Shift - resLow = context.ShiftRightU32(resLow, Const(shift)); - resLow = context.BitwiseOr(resLow, context.ShiftLeft(resHigh, Const(32 - shift))); - resHigh = resSigned - ? context.ShiftRightS32(resHigh, Const(shift)) - : context.ShiftRightU32(resHigh, Const(shift)); - } - - Operand res = resLow; - - if (op.Sat) - { - Operand sign = context.ShiftRightS32(resHigh, Const(31)); - - if (resSigned) - { - Operand overflow = context.ICompareNotEqual(resHigh, context.ShiftRightS32(resLow, Const(31))); - Operand clampValue = context.ConditionalSelect(sign, Const(int.MinValue), Const(int.MaxValue)); - res = context.ConditionalSelect(overflow, clampValue, resLow); - } - else - { - Operand overflow = context.ICompareNotEqual(resHigh, Const(0)); - res = context.ConditionalSelect(overflow, context.BitwiseNot(sign), resLow); - } - } - - context.Copy(GetDest(op.Dest), res); - - // TODO: CC. - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitVideoMinMax.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitVideoMinMax.cs deleted file mode 100644 index 67b185ab..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitVideoMinMax.cs +++ /dev/null @@ -1,183 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; - -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - public static void Vmnmx(EmitterContext context) - { - InstVmnmx op = context.GetOp<InstVmnmx>(); - - Operand srcA = InstEmitAluHelper.Extend(context, GetSrcReg(context, op.SrcA), op.ASelect); - Operand srcC = GetSrcReg(context, op.SrcC); - Operand srcB; - - if (op.BVideo) - { - srcB = InstEmitAluHelper.Extend(context, GetSrcReg(context, op.SrcB), op.BSelect); - } - else - { - int imm = op.Imm16; - - if ((op.BSelect & VectorSelect.S8B0) != 0) - { - imm = (imm << 16) >> 16; - } - - srcB = Const(imm); - } - - Operand res; - - bool resSigned; - - if ((op.ASelect & VectorSelect.S8B0) != (op.BSelect & VectorSelect.S8B0)) - { - // Signedness is different, but for max, result will always fit a U32, - // since one of the inputs can't be negative, and the result is the one - // with highest value. For min, it will always fit on a S32, since - // one of the input can't be greater than INT_MAX and we want the lowest value. - resSigned = !op.Mn; - - res = op.Mn ? context.IMaximumU32(srcA, srcB) : context.IMinimumS32(srcA, srcB); - - if ((op.ASelect & VectorSelect.S8B0) != 0) - { - Operand isBGtIntMax = context.ICompareLess(srcB, Const(0)); - - res = context.ConditionalSelect(isBGtIntMax, srcB, res); - } - else - { - Operand isAGtIntMax = context.ICompareLess(srcA, Const(0)); - - res = context.ConditionalSelect(isAGtIntMax, srcA, res); - } - } - else - { - // Ra and Rb have the same signedness, so doesn't matter which one we test. - resSigned = (op.ASelect & VectorSelect.S8B0) != 0; - - if (op.Mn) - { - res = resSigned - ? context.IMaximumS32(srcA, srcB) - : context.IMaximumU32(srcA, srcB); - } - else - { - res = resSigned - ? context.IMinimumS32(srcA, srcB) - : context.IMinimumU32(srcA, srcB); - } - } - - if (op.Sat) - { - if (op.DFormat && !resSigned) - { - res = context.IMinimumU32(res, Const(int.MaxValue)); - } - else if (!op.DFormat && resSigned) - { - res = context.IMaximumS32(res, Const(0)); - } - } - - switch (op.VideoOp) - { - case VideoOp.Acc: - res = context.IAdd(res, srcC); - break; - case VideoOp.Max: - res = op.DFormat ? context.IMaximumS32(res, srcC) : context.IMaximumU32(res, srcC); - break; - case VideoOp.Min: - res = op.DFormat ? context.IMinimumS32(res, srcC) : context.IMinimumU32(res, srcC); - break; - case VideoOp.Mrg16h: - res = context.BitfieldInsert(srcC, res, Const(16), Const(16)); - break; - case VideoOp.Mrg16l: - res = context.BitfieldInsert(srcC, res, Const(0), Const(16)); - break; - case VideoOp.Mrg8b0: - res = context.BitfieldInsert(srcC, res, Const(0), Const(8)); - break; - case VideoOp.Mrg8b2: - res = context.BitfieldInsert(srcC, res, Const(16), Const(8)); - break; - } - - context.Copy(GetDest(op.Dest), res); - } - - public static void Vsetp(EmitterContext context) - { - InstVsetp op = context.GetOp<InstVsetp>(); - - Operand srcA = InstEmitAluHelper.Extend(context, GetSrcReg(context, op.SrcA), op.ASelect); - Operand srcB; - - if (op.BVideo) - { - srcB = InstEmitAluHelper.Extend(context, GetSrcReg(context, op.SrcB), op.BSelect); - } - else - { - int imm = op.Imm16; - - if ((op.BSelect & VectorSelect.S8B0) != 0) - { - imm = (imm << 16) >> 16; - } - - srcB = Const(imm); - } - - Operand p0Res; - - bool signedA = (op.ASelect & VectorSelect.S8B0) != 0; - bool signedB = (op.BSelect & VectorSelect.S8B0) != 0; - - if (signedA != signedB) - { - bool a32 = (op.ASelect & ~VectorSelect.S8B0) == VectorSelect.U32; - bool b32 = (op.BSelect & ~VectorSelect.S8B0) == VectorSelect.U32; - - if (!a32 && !b32) - { - // Both values are extended small integer and can always fit in a S32, just do a signed comparison. - p0Res = GetIntComparison(context, op.VComp, srcA, srcB, isSigned: true, extended: false); - } - else - { - // TODO: Mismatching sign case. - p0Res = Const(0); - } - } - else - { - // Sign matches, just do a regular comparison. - p0Res = GetIntComparison(context, op.VComp, srcA, srcB, signedA, extended: false); - } - - Operand p1Res = context.BitwiseNot(p0Res); - - Operand pred = GetPredicate(context, op.SrcPred, op.SrcPredInv); - - p0Res = InstEmitAluHelper.GetPredLogicalOp(context, op.BoolOp, p0Res, pred); - p1Res = InstEmitAluHelper.GetPredLogicalOp(context, op.BoolOp, p1Res, pred); - - context.Copy(Register(op.DestPred, RegisterType.Predicate), p0Res); - context.Copy(Register(op.DestPredInv, RegisterType.Predicate), p1Res); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitWarp.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitWarp.cs deleted file mode 100644 index 3c833613..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitWarp.cs +++ /dev/null @@ -1,84 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; - -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - public static void Fswzadd(EmitterContext context) - { - InstFswzadd op = context.GetOp<InstFswzadd>(); - - Operand srcA = GetSrcReg(context, op.SrcA); - Operand srcB = GetSrcReg(context, op.SrcB); - Operand dest = GetDest(op.Dest); - - context.Copy(dest, context.FPSwizzleAdd(srcA, srcB, op.PnWord)); - - InstEmitAluHelper.SetFPZnFlags(context, dest, op.WriteCC); - } - - public static void Shfl(EmitterContext context) - { - InstShfl op = context.GetOp<InstShfl>(); - - Operand pred = Register(op.DestPred, RegisterType.Predicate); - - Operand srcA = GetSrcReg(context, op.SrcA); - - Operand srcB = op.BFixShfl ? Const(op.SrcBImm) : GetSrcReg(context, op.SrcB); - Operand srcC = op.CFixShfl ? Const(op.SrcCImm) : GetSrcReg(context, op.SrcC); - - (Operand res, Operand valid) = op.ShflMode switch - { - ShflMode.Idx => context.Shuffle(srcA, srcB, srcC), - ShflMode.Up => context.ShuffleUp(srcA, srcB, srcC), - ShflMode.Down => context.ShuffleDown(srcA, srcB, srcC), - ShflMode.Bfly => context.ShuffleXor(srcA, srcB, srcC), - _ => (null, null) - }; - - context.Copy(GetDest(op.Dest), res); - context.Copy(pred, valid); - } - - public static void Vote(EmitterContext context) - { - InstVote op = context.GetOp<InstVote>(); - - Operand pred = GetPredicate(context, op.SrcPred, op.SrcPredInv); - Operand res = null; - - switch (op.VoteMode) - { - case VoteMode.All: - res = context.VoteAll(pred); - break; - case VoteMode.Any: - res = context.VoteAny(pred); - break; - case VoteMode.Eq: - res = context.VoteAllEqual(pred); - break; - } - - if (res != null) - { - context.Copy(Register(op.VpDest, RegisterType.Predicate), res); - } - else - { - context.Config.GpuAccessor.Log($"Invalid vote operation: {op.VoteMode}."); - } - - if (op.Dest != RegisterConsts.RegisterZeroIndex) - { - context.Copy(GetDest(op.Dest), context.Ballot(pred)); - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitter.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitter.cs deleted file mode 100644 index 91c740b6..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitter.cs +++ /dev/null @@ -1,6 +0,0 @@ -using Ryujinx.Graphics.Shader.Translation; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - delegate void InstEmitter(EmitterContext context); -}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/Lop3Expression.cs b/Ryujinx.Graphics.Shader/Instructions/Lop3Expression.cs deleted file mode 100644 index 6217ce53..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/Lop3Expression.cs +++ /dev/null @@ -1,141 +0,0 @@ -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; - -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static class Lop3Expression - { - private enum TruthTable : byte - { - False = 0x00, // false - True = 0xff, // true - In = 0xf0, // a - And2 = 0xc0, // a & b - Or2 = 0xfc, // a | b - Xor2 = 0x3c, // a ^ b - And3 = 0x80, // a & b & c - Or3 = 0xfe, // a | b | c - XorAnd = 0x60, // a & (b ^ c) - XorOr = 0xf6, // a | (b ^ c) - OrAnd = 0xe0, // a & (b | c) - AndOr = 0xf8, // a | (b & c) - Onehot = 0x16, // (a & !b & !c) | (!a & b & !c) | (!a & !b & c) - Only one value is true. - Majority = 0xe8, // Popcount(a, b, c) >= 2 - Gamble = 0x81, // (a & b & c) | (!a & !b & !c) - All on or all off - InverseGamble = 0x7e, // Inverse of Gamble - Dot = 0x1a, // a ^ (c | (a & b)) - Mux = 0xca, // a ? b : c - AndXor = 0x78, // a ^ (b & c) - OrXor = 0x1e, // a ^ (b | c) - Xor3 = 0x96, // a ^ b ^ c - } - - public static Operand GetFromTruthTable(EmitterContext context, Operand srcA, Operand srcB, Operand srcC, int imm) - { - for (int i = 0; i < 0x40; i++) - { - TruthTable currImm = (TruthTable)imm; - - Operand x = srcA; - Operand y = srcB; - Operand z = srcC; - - if ((i & 0x01) != 0) - { - (x, y) = (y, x); - currImm = PermuteTable(currImm, 7, 6, 3, 2, 5, 4, 1, 0); - } - - if ((i & 0x02) != 0) - { - (x, z) = (z, x); - currImm = PermuteTable(currImm, 7, 3, 5, 1, 6, 2, 4, 0); - } - - if ((i & 0x04) != 0) - { - (y, z) = (z, y); - currImm = PermuteTable(currImm, 7, 5, 6, 4, 3, 1, 2, 0); - } - - if ((i & 0x08) != 0) - { - x = context.BitwiseNot(x); - currImm = PermuteTable(currImm, 3, 2, 1, 0, 7, 6, 5, 4); - } - - if ((i & 0x10) != 0) - { - y = context.BitwiseNot(y); - currImm = PermuteTable(currImm, 5, 4, 7, 6, 1, 0, 3, 2); - } - - if ((i & 0x20) != 0) - { - z = context.BitwiseNot(z); - currImm = PermuteTable(currImm, 6, 7, 4, 5, 2, 3, 0, 1); - } - - Operand result = GetExpr(currImm, context, x, y, z); - if (result != null) - { - return result; - } - - Operand notResult = GetExpr((TruthTable)((~(int)currImm) & 0xff), context, x, y, z); - if (notResult != null) - { - return context.BitwiseNot(notResult); - } - } - - return null; - } - - private static Operand GetExpr(TruthTable imm, EmitterContext context, Operand x, Operand y, Operand z) - { - return imm switch - { - TruthTable.False => Const(0), - TruthTable.True => Const(-1), - TruthTable.In => x, - TruthTable.And2 => context.BitwiseAnd(x, y), - TruthTable.Or2 => context.BitwiseOr(x, y), - TruthTable.Xor2 => context.BitwiseExclusiveOr(x, y), - TruthTable.And3 => context.BitwiseAnd(x, context.BitwiseAnd(y, z)), - TruthTable.Or3 => context.BitwiseOr(x, context.BitwiseOr(y, z)), - TruthTable.XorAnd => context.BitwiseAnd(x, context.BitwiseExclusiveOr(y, z)), - TruthTable.XorOr => context.BitwiseOr(x, context.BitwiseExclusiveOr(y, z)), - TruthTable.OrAnd => context.BitwiseAnd(x, context.BitwiseOr(y, z)), - TruthTable.AndOr => context.BitwiseOr(x, context.BitwiseAnd(y, z)), - TruthTable.Onehot => context.BitwiseExclusiveOr(context.BitwiseOr(x, y), context.BitwiseOr(z, context.BitwiseAnd(x, y))), - TruthTable.Majority => context.BitwiseAnd(context.BitwiseOr(x, y), context.BitwiseOr(z, context.BitwiseAnd(x, y))), - TruthTable.InverseGamble => context.BitwiseOr(context.BitwiseExclusiveOr(x, y), context.BitwiseExclusiveOr(x, z)), - TruthTable.Dot => context.BitwiseAnd(context.BitwiseExclusiveOr(x, z), context.BitwiseOr(context.BitwiseNot(y), z)), - TruthTable.Mux => context.BitwiseOr(context.BitwiseAnd(x, y), context.BitwiseAnd(context.BitwiseNot(x), z)), - TruthTable.AndXor => context.BitwiseExclusiveOr(x, context.BitwiseAnd(y, z)), - TruthTable.OrXor => context.BitwiseExclusiveOr(x, context.BitwiseOr(y, z)), - TruthTable.Xor3 => context.BitwiseExclusiveOr(x, context.BitwiseExclusiveOr(y, z)), - _ => null - }; - } - - private static TruthTable PermuteTable(TruthTable imm, int bit7, int bit6, int bit5, int bit4, int bit3, int bit2, int bit1, int bit0) - { - int result = 0; - - result |= (((int)imm >> 0) & 1) << bit0; - result |= (((int)imm >> 1) & 1) << bit1; - result |= (((int)imm >> 2) & 1) << bit2; - result |= (((int)imm >> 3) & 1) << bit3; - result |= (((int)imm >> 4) & 1) << bit4; - result |= (((int)imm >> 5) & 1) << bit5; - result |= (((int)imm >> 6) & 1) << bit6; - result |= (((int)imm >> 7) & 1) << bit7; - - return (TruthTable)result; - } - } -}
\ No newline at end of file |
