diff --git a/Ryujinx.Graphics.GAL/Capabilities.cs b/Ryujinx.Graphics.GAL/Capabilities.cs
index 6e5329b2..20bd87c6 100644
--- a/Ryujinx.Graphics.GAL/Capabilities.cs
+++ b/Ryujinx.Graphics.GAL/Capabilities.cs
@@ -6,6 +6,8 @@ namespace Ryujinx.Graphics.GAL
public bool HasVectorIndexingBug { get; }
public bool SupportsAstcCompression { get; }
+ public bool SupportsFragmentShaderInterlock { get; }
+ public bool SupportsFragmentShaderOrderingIntel { get; }
public bool SupportsImageLoadFormatted { get; }
public bool SupportsMismatchingViewFormat { get; }
public bool SupportsNonConstantTextureOffset { get; }
@@ -22,6 +24,8 @@ namespace Ryujinx.Graphics.GAL
bool hasFrontFacingBug,
bool hasVectorIndexingBug,
bool supportsAstcCompression,
+ bool supportsFragmentShaderInterlock,
+ bool supportsFragmentShaderOrderingIntel,
bool supportsImageLoadFormatted,
bool supportsMismatchingViewFormat,
bool supportsNonConstantTextureOffset,
@@ -36,6 +40,8 @@ namespace Ryujinx.Graphics.GAL
HasFrontFacingBug = hasFrontFacingBug;
HasVectorIndexingBug = hasVectorIndexingBug;
SupportsAstcCompression = supportsAstcCompression;
+ SupportsFragmentShaderInterlock = supportsFragmentShaderInterlock;
+ SupportsFragmentShaderOrderingIntel = supportsFragmentShaderOrderingIntel;
SupportsImageLoadFormatted = supportsImageLoadFormatted;
SupportsMismatchingViewFormat = supportsMismatchingViewFormat;
SupportsNonConstantTextureOffset = supportsNonConstantTextureOffset;
diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
index 619a8c5f..be5e7ab9 100644
--- a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
@@ -40,7 +40,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
///
/// Version of the codegen (to be changed when codegen or guest format change).
///
- private const ulong ShaderCodeGenVersion = 2741;
+ private const ulong ShaderCodeGenVersion = 2768;
// Progress reporting helpers
private volatile int _shaderCount;
diff --git a/Ryujinx.Graphics.Gpu/Shader/TextureDescriptorCapableGpuAccessor.cs b/Ryujinx.Graphics.Gpu/Shader/TextureDescriptorCapableGpuAccessor.cs
index 40353850..50039a90 100644
--- a/Ryujinx.Graphics.Gpu/Shader/TextureDescriptorCapableGpuAccessor.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/TextureDescriptorCapableGpuAccessor.cs
@@ -36,6 +36,18 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// Host storage buffer alignment in bytes
public int QueryHostStorageBufferOffsetAlignment() => _context.Capabilities.StorageBufferOffsetAlignment;
+ ///
+ /// Queries host support for fragment shader ordering critical sections on the shader code.
+ ///
+ /// True if fragment shader interlock is supported, false otherwise
+ public bool QueryHostSupportsFragmentShaderInterlock() => _context.Capabilities.SupportsFragmentShaderInterlock;
+
+ ///
+ /// Queries host support for fragment shader ordering scoped critical sections on the shader code.
+ ///
+ /// True if fragment shader ordering is supported, false otherwise
+ public bool QueryHostSupportsFragmentShaderOrderingIntel() => _context.Capabilities.SupportsFragmentShaderOrderingIntel;
+
///
/// Queries host support for readable images without a explicit format declaration on the shader.
///
diff --git a/Ryujinx.Graphics.OpenGL/HwCapabilities.cs b/Ryujinx.Graphics.OpenGL/HwCapabilities.cs
index 9a62bb2e..ec9bd4a2 100644
--- a/Ryujinx.Graphics.OpenGL/HwCapabilities.cs
+++ b/Ryujinx.Graphics.OpenGL/HwCapabilities.cs
@@ -6,7 +6,10 @@ namespace Ryujinx.Graphics.OpenGL
static class HwCapabilities
{
private static readonly Lazy _supportsAstcCompression = new Lazy(() => HasExtension("GL_KHR_texture_compression_astc_ldr"));
+ private static readonly Lazy _supportsFragmentShaderInterlock = new Lazy(() => HasExtension("GL_ARB_fragment_shader_interlock"));
+ private static readonly Lazy _supportsFragmentShaderOrdering = new Lazy(() => HasExtension("GL_INTEL_fragment_shader_ordering"));
private static readonly Lazy _supportsImageLoadFormatted = new Lazy(() => HasExtension("GL_EXT_shader_image_load_formatted"));
+ private static readonly Lazy _supportsIndirectParameters = new Lazy(() => HasExtension("GL_ARB_indirect_parameters"));
private static readonly Lazy _supportsParallelShaderCompile = new Lazy(() => HasExtension("GL_ARB_parallel_shader_compile"));
private static readonly Lazy _supportsPolygonOffsetClamp = new Lazy(() => HasExtension("GL_EXT_polygon_offset_clamp"));
private static readonly Lazy _supportsQuads = new Lazy(SupportsQuadsCheck);
@@ -14,7 +17,6 @@ namespace Ryujinx.Graphics.OpenGL
private static readonly Lazy _supportsShaderBallot = new Lazy(() => HasExtension("GL_ARB_shader_ballot"));
private static readonly Lazy _supportsTextureShadowLod = new Lazy(() => HasExtension("GL_EXT_texture_shadow_lod"));
private static readonly Lazy _supportsViewportSwizzle = new Lazy(() => HasExtension("GL_NV_viewport_swizzle"));
- private static readonly Lazy _supportsIndirectParameters = new Lazy(() => HasExtension("GL_ARB_indirect_parameters"));
private static readonly Lazy _maximumComputeSharedMemorySize = new Lazy(() => GetLimit(All.MaxComputeSharedMemorySize));
private static readonly Lazy _storageBufferOffsetAlignment = new Lazy(() => GetLimit(All.ShaderStorageBufferOffsetAlignment));
@@ -41,7 +43,10 @@ namespace Ryujinx.Graphics.OpenGL
public static bool UsePersistentBufferForFlush => _gpuVendor.Value == GpuVendor.AmdWindows || _gpuVendor.Value == GpuVendor.Nvidia;
public static bool SupportsAstcCompression => _supportsAstcCompression.Value;
+ public static bool SupportsFragmentShaderInterlock => _supportsFragmentShaderInterlock.Value;
+ public static bool SupportsFragmentShaderOrdering => _supportsFragmentShaderOrdering.Value;
public static bool SupportsImageLoadFormatted => _supportsImageLoadFormatted.Value;
+ public static bool SupportsIndirectParameters => _supportsIndirectParameters.Value;
public static bool SupportsParallelShaderCompile => _supportsParallelShaderCompile.Value;
public static bool SupportsPolygonOffsetClamp => _supportsPolygonOffsetClamp.Value;
public static bool SupportsQuads => _supportsQuads.Value;
@@ -49,7 +54,6 @@ namespace Ryujinx.Graphics.OpenGL
public static bool SupportsShaderBallot => _supportsShaderBallot.Value;
public static bool SupportsTextureShadowLod => _supportsTextureShadowLod.Value;
public static bool SupportsViewportSwizzle => _supportsViewportSwizzle.Value;
- public static bool SupportsIndirectParameters => _supportsIndirectParameters.Value;
public static bool SupportsMismatchingViewFormat => _gpuVendor.Value != GpuVendor.AmdWindows && _gpuVendor.Value != GpuVendor.IntelWindows;
public static bool SupportsNonConstantTextureOffset => _gpuVendor.Value == GpuVendor.Nvidia;
diff --git a/Ryujinx.Graphics.OpenGL/Renderer.cs b/Ryujinx.Graphics.OpenGL/Renderer.cs
index 768c7450..25b762b2 100644
--- a/Ryujinx.Graphics.OpenGL/Renderer.cs
+++ b/Ryujinx.Graphics.OpenGL/Renderer.cs
@@ -104,6 +104,8 @@ namespace Ryujinx.Graphics.OpenGL
HwCapabilities.Vendor == HwCapabilities.GpuVendor.IntelWindows,
HwCapabilities.Vendor == HwCapabilities.GpuVendor.AmdWindows,
HwCapabilities.SupportsAstcCompression,
+ HwCapabilities.SupportsFragmentShaderInterlock,
+ HwCapabilities.SupportsFragmentShaderOrdering,
HwCapabilities.SupportsImageLoadFormatted,
HwCapabilities.SupportsMismatchingViewFormat,
HwCapabilities.SupportsNonConstantTextureOffset,
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
index 85288afa..7dcd1671 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
@@ -32,6 +32,17 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{
context.AppendLine("#extension GL_ARB_compute_shader : enable");
}
+ else if (context.Config.Stage == ShaderStage.Fragment)
+ {
+ if (context.Config.GpuAccessor.QueryHostSupportsFragmentShaderInterlock())
+ {
+ context.AppendLine("#extension GL_ARB_fragment_shader_interlock : enable");
+ }
+ else if (context.Config.GpuAccessor.QueryHostSupportsFragmentShaderOrderingIntel())
+ {
+ context.AppendLine("#extension GL_INTEL_fragment_shader_ordering : enable");
+ }
+ }
if (context.Config.GpPassthrough)
{
@@ -431,6 +442,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
string imageTypeName = descriptor.Type.ToGlslImageType(descriptor.Format.GetComponentType());
+ if (descriptor.Flags.HasFlag(TextureUsageFlags.ImageCoherent))
+ {
+ imageTypeName = "coherent " + imageTypeName;
+ }
+
string layout = descriptor.Format.ToGlslFormat();
if (!string.IsNullOrEmpty(layout))
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs
index 077737c8..3af120f8 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs
@@ -117,7 +117,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{
if (node is AstOperation operation)
{
- context.AppendLine(InstGen.GetExpression(context, operation) + ";");
+ string expr = InstGen.GetExpression(context, operation);
+
+ if (expr != null)
+ {
+ context.AppendLine(expr + ";");
+ }
}
else if (node is AstAssignment assignment)
{
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs
index 4f059149..1acac745 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs
@@ -4,6 +4,7 @@ using System;
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenBallot;
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenCall;
+using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenFSI;
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenHelper;
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenMemory;
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenPacking;
@@ -144,6 +145,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
case Instruction.Call:
return Call(context, operation);
+ case Instruction.FSIBegin:
+ return FSIBegin(context);
+
+ case Instruction.FSIEnd:
+ return FSIEnd(context);
+
case Instruction.ImageLoad:
case Instruction.ImageStore:
case Instruction.ImageAtomic:
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenFSI.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenFSI.cs
new file mode 100644
index 00000000..f61a53cb
--- /dev/null
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenFSI.cs
@@ -0,0 +1,29 @@
+namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
+{
+ static class InstGenFSI
+ {
+ public static string FSIBegin(CodeGenContext context)
+ {
+ if (context.Config.GpuAccessor.QueryHostSupportsFragmentShaderInterlock())
+ {
+ return "beginInvocationInterlockARB()";
+ }
+ else if (context.Config.GpuAccessor.QueryHostSupportsFragmentShaderOrderingIntel())
+ {
+ return "beginFragmentShaderOrderingINTEL()";
+ }
+
+ return null;
+ }
+
+ public static string FSIEnd(CodeGenContext context)
+ {
+ if (context.Config.GpuAccessor.QueryHostSupportsFragmentShaderInterlock())
+ {
+ return "endInvocationInterlockARB()";
+ }
+
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs
index c2d59ff7..1fa25399 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs
@@ -65,6 +65,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
Add(Instruction.EmitVertex, InstType.CallNullary, "EmitVertex");
Add(Instruction.EndPrimitive, InstType.CallNullary, "EndPrimitive");
Add(Instruction.ExponentB2, InstType.CallUnary, "exp2");
+ Add(Instruction.FSIBegin, InstType.Special);
+ Add(Instruction.FSIEnd, InstType.Special);
Add(Instruction.FindFirstSetS32, InstType.CallUnary, "findMSB");
Add(Instruction.FindFirstSetU32, InstType.CallUnary, "findMSB");
Add(Instruction.Floor, InstType.CallUnary, "floor");
diff --git a/Ryujinx.Graphics.Shader/Decoders/DecodedFunction.cs b/Ryujinx.Graphics.Shader/Decoders/DecodedFunction.cs
new file mode 100644
index 00000000..7a172fe6
--- /dev/null
+++ b/Ryujinx.Graphics.Shader/Decoders/DecodedFunction.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+
+namespace Ryujinx.Graphics.Shader.Decoders
+{
+ class DecodedFunction
+ {
+ private readonly HashSet _callers;
+
+ public bool IsCompilerGenerated => Type != FunctionType.User;
+ public FunctionType Type { get; set; }
+ public int Id { get; set; }
+
+ public ulong Address { get; }
+ public Block[] Blocks { get; private set; }
+
+ public DecodedFunction(ulong address)
+ {
+ Address = address;
+ _callers = new HashSet();
+ Type = FunctionType.User;
+ Id = -1;
+ }
+
+ public void SetBlocks(Block[] blocks)
+ {
+ if (Blocks != null)
+ {
+ throw new InvalidOperationException("Blocks have already been set.");
+ }
+
+ Blocks = blocks;
+ }
+
+ public void AddCaller(DecodedFunction caller)
+ {
+ _callers.Add(caller);
+ }
+
+ public void RemoveCaller(DecodedFunction caller)
+ {
+ if (_callers.Remove(caller) && _callers.Count == 0)
+ {
+ Type = FunctionType.Unused;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/Decoders/DecodedProgram.cs b/Ryujinx.Graphics.Shader/Decoders/DecodedProgram.cs
new file mode 100644
index 00000000..80de41d7
--- /dev/null
+++ b/Ryujinx.Graphics.Shader/Decoders/DecodedProgram.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Ryujinx.Graphics.Shader.Decoders
+{
+ struct DecodedProgram : IEnumerable
+ {
+ public DecodedFunction MainFunction { get; }
+ private readonly IReadOnlyDictionary _functions;
+ private readonly List _functionsWithId;
+ public int FunctionsWithIdCount => _functionsWithId.Count;
+
+ public DecodedProgram(DecodedFunction mainFunction, IReadOnlyDictionary functions)
+ {
+ MainFunction = mainFunction;
+ _functions = functions;
+ _functionsWithId = new List();
+ }
+
+ public DecodedFunction GetFunctionByAddress(ulong address)
+ {
+ if (_functions.TryGetValue(address, out DecodedFunction function))
+ {
+ return function;
+ }
+
+ return null;
+ }
+
+ public DecodedFunction GetFunctionById(int id)
+ {
+ if ((uint)id >= (uint)_functionsWithId.Count)
+ {
+ throw new ArgumentOutOfRangeException(nameof(id));
+ }
+
+ return _functionsWithId[id];
+ }
+
+ public void AddFunctionAndSetId(DecodedFunction function)
+ {
+ function.Id = _functionsWithId.Count;
+ _functionsWithId.Add(function);
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return _functions.Values.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/Decoders/Decoder.cs b/Ryujinx.Graphics.Shader/Decoders/Decoder.cs
index b446e650..714aaad3 100644
--- a/Ryujinx.Graphics.Shader/Decoders/Decoder.cs
+++ b/Ryujinx.Graphics.Shader/Decoders/Decoder.cs
@@ -10,24 +10,25 @@ namespace Ryujinx.Graphics.Shader.Decoders
{
static class Decoder
{
- public static Block[][] Decode(ShaderConfig config, ulong startAddress)
+ public static DecodedProgram Decode(ShaderConfig config, ulong startAddress)
{
- List funcs = new List();
+ Queue functionsQueue = new Queue();
+ Dictionary functionsVisited = new Dictionary();
- Queue funcQueue = new Queue();
- HashSet funcVisited = new HashSet();
-
- void EnqueueFunction(ulong funcAddress)
+ DecodedFunction EnqueueFunction(ulong address)
{
- if (funcVisited.Add(funcAddress))
+ if (!functionsVisited.TryGetValue(address, out DecodedFunction function))
{
- funcQueue.Enqueue(funcAddress);
+ functionsVisited.Add(address, function = new DecodedFunction(address));
+ functionsQueue.Enqueue(function);
}
+
+ return function;
}
- funcQueue.Enqueue(0);
+ DecodedFunction mainFunction = EnqueueFunction(0);
- while (funcQueue.TryDequeue(out ulong funcAddress))
+ while (functionsQueue.TryDequeue(out DecodedFunction currentFunction))
{
List blocks = new List();
Queue workQueue = new Queue();
@@ -46,7 +47,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
return block;
}
- GetBlock(funcAddress);
+ GetBlock(currentFunction.Address);
bool hasNewTarget;
@@ -108,7 +109,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
if (lastOp.Name == InstName.Cal)
{
- EnqueueFunction(lastOp.GetAbsoluteAddress());
+ EnqueueFunction(lastOp.GetAbsoluteAddress()).AddCaller(currentFunction);
}
else if (lastOp.Name == InstName.Bra)
{
@@ -157,10 +158,10 @@ namespace Ryujinx.Graphics.Shader.Decoders
}
while (hasNewTarget);
- funcs.Add(blocks.ToArray());
+ currentFunction.SetBlocks(blocks.ToArray());
}
- return funcs.ToArray();
+ return new DecodedProgram(mainFunction, functionsVisited);
}
private static bool BinarySearch(List blocks, ulong address, out int index)
diff --git a/Ryujinx.Graphics.Shader/Decoders/FunctionType.cs b/Ryujinx.Graphics.Shader/Decoders/FunctionType.cs
new file mode 100644
index 00000000..6ea6a82a
--- /dev/null
+++ b/Ryujinx.Graphics.Shader/Decoders/FunctionType.cs
@@ -0,0 +1,10 @@
+namespace Ryujinx.Graphics.Shader.Decoders
+{
+ enum FunctionType : byte
+ {
+ User,
+ Unused,
+ BuiltInFSIBegin,
+ BuiltInFSIEnd
+ }
+}
diff --git a/Ryujinx.Graphics.Shader/Decoders/InstDecoders.cs b/Ryujinx.Graphics.Shader/Decoders/InstDecoders.cs
index b61412c6..397e327e 100644
--- a/Ryujinx.Graphics.Shader/Decoders/InstDecoders.cs
+++ b/Ryujinx.Graphics.Shader/Decoders/InstDecoders.cs
@@ -404,13 +404,22 @@ namespace Ryujinx.Graphics.Shader.Decoders
Attr = 3,
}
- enum CacheOp
+ enum CacheOpLd
{
+ Ca = 0,
Cg = 1,
Ci = 2,
Cv = 3,
}
+ enum CacheOpSt
+ {
+ Wb = 0,
+ Cg = 1,
+ Ci = 2,
+ Wt = 3,
+ }
+
enum LsSize
{
U8 = 0,
@@ -1163,19 +1172,19 @@ namespace Ryujinx.Graphics.Shader.Decoders
public CctltOp CctltOp => (CctltOp)((_opcode >> 0) & 0x3);
}
- struct InstContUnsup
+ struct InstCont
{
private ulong _opcode;
- public InstContUnsup(ulong opcode) => _opcode = opcode;
+ public InstCont(ulong opcode) => _opcode = opcode;
public int Pred => (int)((_opcode >> 16) & 0x7);
public bool PredInv => (_opcode & 0x80000) != 0;
public Ccc Ccc => (Ccc)((_opcode >> 0) & 0x1F);
}
- struct InstCsetUnsup
+ struct InstCset
{
private ulong _opcode;
- public InstCsetUnsup(ulong opcode) => _opcode = opcode;
+ public InstCset(ulong opcode) => _opcode = opcode;
public int Dest => (int)((_opcode >> 0) & 0xFF);
public int Pred => (int)((_opcode >> 16) & 0x7);
public bool PredInv => (_opcode & 0x80000) != 0;
@@ -3507,7 +3516,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
public int Pred => (int)((_opcode >> 16) & 0x7);
public bool PredInv => (_opcode & 0x80000) != 0;
public int SrcPred => (int)((_opcode >> 58) & 0x7);
- public CacheOp CacheOp => (CacheOp)((_opcode >> 56) & 0x3);
+ public CacheOpLd CacheOp => (CacheOpLd)((_opcode >> 56) & 0x3);
public LsSize LsSize => (LsSize)((_opcode >> 53) & 0x7);
public bool E => (_opcode & 0x10000000000000) != 0;
public int Imm32 => (int)(_opcode >> 20);
@@ -3536,7 +3545,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
public int Pred => (int)((_opcode >> 16) & 0x7);
public bool PredInv => (_opcode & 0x80000) != 0;
public LsSize LsSize => (LsSize)((_opcode >> 48) & 0x7);
- public CacheOp CacheOp => (CacheOp)((_opcode >> 46) & 0x3);
+ public CacheOpLd CacheOp => (CacheOpLd)((_opcode >> 46) & 0x3);
public bool E => (_opcode & 0x200000000000) != 0;
public int Imm24 => (int)((_opcode >> 20) & 0xFFFFFF);
}
@@ -4502,7 +4511,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
public int Pred => (int)((_opcode >> 16) & 0x7);
public bool PredInv => (_opcode & 0x80000) != 0;
public int SrcPred => (int)((_opcode >> 58) & 0x7);
- public CacheOp Cop => (CacheOp)((_opcode >> 56) & 0x3);
+ public CacheOpSt CacheOp => (CacheOpSt)((_opcode >> 56) & 0x3);
public LsSize LsSize => (LsSize)((_opcode >> 53) & 0x7);
public bool E => (_opcode & 0x10000000000000) != 0;
public int Imm32 => (int)(_opcode >> 20);
@@ -4517,7 +4526,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
public int Pred => (int)((_opcode >> 16) & 0x7);
public bool PredInv => (_opcode & 0x80000) != 0;
public LsSize2 LsSize => (LsSize2)((_opcode >> 48) & 0x7);
- public CacheOp CacheOp => (CacheOp)((_opcode >> 46) & 0x3);
+ public CacheOpSt CacheOp => (CacheOpSt)((_opcode >> 46) & 0x3);
public bool E => (_opcode & 0x200000000000) != 0;
public int Imm24 => (int)((_opcode >> 20) & 0xFFFFFF);
}
@@ -4531,7 +4540,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
public int Pred => (int)((_opcode >> 16) & 0x7);
public bool PredInv => (_opcode & 0x80000) != 0;
public LsSize2 LsSize => (LsSize2)((_opcode >> 48) & 0x7);
- public CacheOp2 CacheOp => (CacheOp2)((_opcode >> 44) & 0x3);
+ public CacheOpSt CacheOp => (CacheOpSt)((_opcode >> 44) & 0x3);
public int Imm24 => (int)((_opcode >> 20) & 0xFFFFFF);
}
@@ -4653,7 +4662,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3);
public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7);
public int DestPred2 => (int)((_opcode >> 30) & 0x7);
- public CacheOp CacheOp => (CacheOp)((_opcode >> 24) & 0x3);
+ public CacheOpLd CacheOp => (CacheOpLd)((_opcode >> 24) & 0x3);
public bool Ba => (_opcode & 0x800000) != 0;
public SuSize Size => (SuSize)((_opcode >> 20) & 0x7);
}
@@ -4670,7 +4679,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
public int TidB => (int)((_opcode >> 36) & 0x1FFF);
public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7);
public int DestPred2 => (int)((_opcode >> 30) & 0x7);
- public CacheOp CacheOp => (CacheOp)((_opcode >> 24) & 0x3);
+ public CacheOpLd CacheOp => (CacheOpLd)((_opcode >> 24) & 0x3);
public bool Ba => (_opcode & 0x800000) != 0;
public SuSize Size => (SuSize)((_opcode >> 20) & 0x7);
}
@@ -4687,7 +4696,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3);
public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7);
public int DestPred2 => (int)((_opcode >> 30) & 0x7);
- public CacheOp CacheOp => (CacheOp)((_opcode >> 24) & 0x3);
+ public CacheOpLd CacheOp => (CacheOpLd)((_opcode >> 24) & 0x3);
public SuRgba Rgba => (SuRgba)((_opcode >> 20) & 0xF);
}
@@ -4703,7 +4712,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
public int TidB => (int)((_opcode >> 36) & 0x1FFF);
public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7);
public int DestPred2 => (int)((_opcode >> 30) & 0x7);
- public CacheOp CacheOp => (CacheOp)((_opcode >> 24) & 0x3);
+ public CacheOpLd CacheOp => (CacheOpLd)((_opcode >> 24) & 0x3);
public SuRgba Rgba => (SuRgba)((_opcode >> 20) & 0xF);
}
@@ -4750,7 +4759,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
public bool PredInv => (_opcode & 0x80000) != 0;
public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3);
public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7);
- public CacheOp CacheOp => (CacheOp)((_opcode >> 24) & 0x3);
+ public CacheOpSt CacheOp => (CacheOpSt)((_opcode >> 24) & 0x3);
public bool Ba => (_opcode & 0x800000) != 0;
public SuSize Size => (SuSize)((_opcode >> 20) & 0x7);
}
@@ -4766,7 +4775,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3);
public int TidB => (int)((_opcode >> 36) & 0x1FFF);
public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7);
- public CacheOp CacheOp => (CacheOp)((_opcode >> 24) & 0x3);
+ public CacheOpSt CacheOp => (CacheOpSt)((_opcode >> 24) & 0x3);
public bool Ba => (_opcode & 0x800000) != 0;
public SuSize Size => (SuSize)((_opcode >> 20) & 0x7);
}
@@ -4782,7 +4791,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
public bool PredInv => (_opcode & 0x80000) != 0;
public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3);
public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7);
- public CacheOp CacheOp => (CacheOp)((_opcode >> 24) & 0x3);
+ public CacheOpSt CacheOp => (CacheOpSt)((_opcode >> 24) & 0x3);
public SuRgba Rgba => (SuRgba)((_opcode >> 20) & 0xF);
}
@@ -4797,7 +4806,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3);
public int TidB => (int)((_opcode >> 36) & 0x1FFF);
public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7);
- public CacheOp CacheOp => (CacheOp)((_opcode >> 24) & 0x3);
+ public CacheOpSt CacheOp => (CacheOpSt)((_opcode >> 24) & 0x3);
public SuRgba Rgba => (SuRgba)((_opcode >> 20) & 0xF);
}
diff --git a/Ryujinx.Graphics.Shader/Decoders/InstProps.cs b/Ryujinx.Graphics.Shader/Decoders/InstProps.cs
index 7d329a81..1af94ab5 100644
--- a/Ryujinx.Graphics.Shader/Decoders/InstProps.cs
+++ b/Ryujinx.Graphics.Shader/Decoders/InstProps.cs
@@ -7,14 +7,22 @@ namespace Ryujinx.Graphics.Shader.Decoders
Rd2 = 1 << 1,
Ra = 1 << 2,
Rb = 1 << 3,
- Ib = 1 << 4,
- Rc = 1 << 5,
- Pd = 1 << 6,
- Pd2 = 1 << 7,
- Pdn = 1 << 8,
- Tex = 1 << 9,
- TexB = 1 << 10,
- Bra = 1 << 11,
- NoPred = 1 << 12
+ Rb2 = 1 << 4,
+ Ib = 1 << 5,
+ Rc = 1 << 6,
+
+ Pd = 1 << 7,
+ LPd = 2 << 7,
+ SPd = 3 << 7,
+ TPd = 4 << 7,
+ VPd = 5 << 7,
+ PdMask = 7 << 7,
+
+ Pdn = 1 << 10,
+ Ps = 1 << 11,
+ Tex = 1 << 12,
+ TexB = 1 << 13,
+ Bra = 1 << 14,
+ NoPred = 1 << 15
}
}
\ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/Decoders/InstTable.cs b/Ryujinx.Graphics.Shader/Decoders/InstTable.cs
index c971d646..2d91f21a 100644
--- a/Ryujinx.Graphics.Shader/Decoders/InstTable.cs
+++ b/Ryujinx.Graphics.Shader/Decoders/InstTable.cs
@@ -32,13 +32,13 @@ namespace Ryujinx.Graphics.Shader.Decoders
#region Instructions
Add("1110111110100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Al2p, InstEmit.Al2p, InstProps.Rd | InstProps.Ra);
Add("1110111111011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ald, InstEmit.Ald, InstProps.Rd | InstProps.Ra);
- Add("1110111111110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ast, InstEmit.Ast, InstProps.Ra | InstProps.Rc);
+ Add("1110111111110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ast, InstEmit.Ast, InstProps.Ra | InstProps.Rb2 | InstProps.Rc);
Add("11101101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Atom, InstEmit.Atom, InstProps.Rd | InstProps.Ra | InstProps.Rb);
Add("111011101111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.AtomCas, InstEmit.AtomCas, InstProps.Rd | InstProps.Ra | InstProps.Rb);
Add("11101100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Atoms, InstEmit.Atoms, InstProps.Rd | InstProps.Ra | InstProps.Rb);
Add("111011100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.AtomsCas, InstEmit.AtomsCas, InstProps.Rd | InstProps.Ra | InstProps.Rb);
- Add("1111000010111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.B2r, InstEmit.B2r, InstProps.Rd | InstProps.Ra);
- Add("1111000010101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Bar, InstEmit.Bar, InstProps.Ra);
+ Add("1111000010111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.B2r, InstEmit.B2r, InstProps.Rd | InstProps.Ra | InstProps.VPd);
+ Add("1111000010101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Bar, InstEmit.Bar, InstProps.Ra | InstProps.Ps);
Add("0101110000000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Bfe, InstEmit.BfeR, InstProps.Rd | InstProps.Ra | InstProps.Rb);
Add("0011100x00000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Bfe, InstEmit.BfeI, InstProps.Rd | InstProps.Ra | InstProps.Ib);
Add("0100110000000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Bfe, InstEmit.BfeC, InstProps.Rd | InstProps.Ra);
@@ -56,8 +56,8 @@ namespace Ryujinx.Graphics.Shader.Decoders
Add("1110101111110xx0000000000000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Cctlt, InstEmit.Cctlt);
Add("1110101111101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Cctlt, InstEmit.Cctlt, InstProps.Rc);
Add("111000110101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Cont, InstEmit.Cont);
- Add("0101000010011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Cset, InstEmit.Cset, InstProps.Rd);
- Add("0101000010100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Csetp, InstEmit.Csetp, InstProps.Pd | InstProps.Pdn);
+ Add("0101000010011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Cset, InstEmit.Cset, InstProps.Rd | InstProps.Ps);
+ Add("0101000010100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Csetp, InstEmit.Csetp, InstProps.Pd | InstProps.Pdn | InstProps.Ps);
Add("0101000011001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Cs2r, InstEmit.Cs2r, InstProps.Rd);
Add("0101110001110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dadd, InstEmit.DaddR, InstProps.Rd | InstProps.Ra | InstProps.Rb);
Add("0011100x01110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dadd, InstEmit.DaddI, InstProps.Rd | InstProps.Ra | InstProps.Ib);
@@ -67,18 +67,18 @@ namespace Ryujinx.Graphics.Shader.Decoders
Add("0011011x0111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dfma, InstEmit.DfmaI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Rc);
Add("010010110111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dfma, InstEmit.DfmaC, InstProps.Rd | InstProps.Ra | InstProps.Rc);
Add("010100110111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dfma, InstEmit.DfmaRc, InstProps.Rd | InstProps.Ra | InstProps.Rc);
- Add("0101110001010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dmnmx, InstEmit.DmnmxR, InstProps.Rd | InstProps.Ra | InstProps.Rb);
- Add("0011100x01010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dmnmx, InstEmit.DmnmxI, InstProps.Rd | InstProps.Ra | InstProps.Ib);
- Add("0100110001010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dmnmx, InstEmit.DmnmxC, InstProps.Rd | InstProps.Ra);
+ Add("0101110001010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dmnmx, InstEmit.DmnmxR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Ps);
+ Add("0011100x01010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dmnmx, InstEmit.DmnmxI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Ps);
+ Add("0100110001010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dmnmx, InstEmit.DmnmxC, InstProps.Rd | InstProps.Ra | InstProps.Ps);
Add("0101110010000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dmul, InstEmit.DmulR, InstProps.Rd | InstProps.Ra | InstProps.Rb);
Add("0011100x10000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dmul, InstEmit.DmulI, InstProps.Rd | InstProps.Ra | InstProps.Ib);
Add("0100110010000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dmul, InstEmit.DmulC, InstProps.Rd | InstProps.Ra);
- Add("010110010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dset, InstEmit.DsetR, InstProps.Rd | InstProps.Ra | InstProps.Rb);
- Add("0011001x0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dset, InstEmit.DsetI, InstProps.Rd | InstProps.Ra | InstProps.Ib);
- Add("010010010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dset, InstEmit.DsetC, InstProps.Rd | InstProps.Ra);
- Add("010110111000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dsetp, InstEmit.DsetpR, InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Pdn);
- Add("0011011x1000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dsetp, InstEmit.DsetpI, InstProps.Ra | InstProps.Ib | InstProps.Pd | InstProps.Pdn);
- Add("010010111000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dsetp, InstEmit.DsetpC, InstProps.Ra | InstProps.Pd | InstProps.Pdn);
+ Add("010110010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dset, InstEmit.DsetR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Ps);
+ Add("0011001x0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dset, InstEmit.DsetI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Ps);
+ Add("010010010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dset, InstEmit.DsetC, InstProps.Rd | InstProps.Ra | InstProps.Ps);
+ Add("010110111000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dsetp, InstEmit.DsetpR, InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
+ Add("0011011x1000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dsetp, InstEmit.DsetpI, InstProps.Ra | InstProps.Ib | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
+ Add("010010111000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dsetp, InstEmit.DsetpC, InstProps.Ra | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
Add("111000110000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Exit, InstEmit.Exit, InstProps.Bra);
Add("0101110010101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.F2f, InstEmit.F2fR, InstProps.Rd | InstProps.Rb);
Add("0011100x10101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.F2f, InstEmit.F2fI, InstProps.Rd | InstProps.Ib);
@@ -105,19 +105,19 @@ namespace Ryujinx.Graphics.Shader.Decoders
Add("0101110000110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Flo, InstEmit.FloR, InstProps.Rd | InstProps.Rb);
Add("0011100x00110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Flo, InstEmit.FloI, InstProps.Rd | InstProps.Ib);
Add("0100110000110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Flo, InstEmit.FloC, InstProps.Rd);
- Add("0101110001100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmnmx, InstEmit.FmnmxR, InstProps.Rd | InstProps.Ra | InstProps.Rb);
- Add("0011100x01100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmnmx, InstEmit.FmnmxI, InstProps.Rd | InstProps.Ra | InstProps.Ib);
- Add("0100110001100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmnmx, InstEmit.FmnmxC, InstProps.Rd | InstProps.Ra);
+ Add("0101110001100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmnmx, InstEmit.FmnmxR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Ps);
+ Add("0011100x01100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmnmx, InstEmit.FmnmxI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Ps);
+ Add("0100110001100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmnmx, InstEmit.FmnmxC, InstProps.Rd | InstProps.Ra | InstProps.Ps);
Add("0101110001101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmul, InstEmit.FmulR, InstProps.Rd | InstProps.Ra | InstProps.Rb);
Add("0011100x01101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmul, InstEmit.FmulI, InstProps.Rd | InstProps.Ra | InstProps.Ib);
Add("0100110001101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmul, InstEmit.FmulC, InstProps.Rd | InstProps.Ra);
Add("00011110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmul32i, InstEmit.Fmul32i, InstProps.Rd | InstProps.Ra);
- Add("01011000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fset, InstEmit.FsetR, InstProps.Rd | InstProps.Ra | InstProps.Rb);
- Add("0011000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fset, InstEmit.FsetI, InstProps.Rd | InstProps.Ra | InstProps.Ib);
- Add("01001000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fset, InstEmit.FsetC, InstProps.Rd | InstProps.Ra);
- Add("010110111011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fsetp, InstEmit.FsetpR, InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Pdn);
- Add("0011011x1011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fsetp, InstEmit.FsetpI, InstProps.Ra | InstProps.Ib | InstProps.Pd | InstProps.Pdn);
- Add("010010111011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fsetp, InstEmit.FsetpC, InstProps.Ra | InstProps.Pd | InstProps.Pdn);
+ Add("01011000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fset, InstEmit.FsetR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Ps);
+ Add("0011000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fset, InstEmit.FsetI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Ps);
+ Add("01001000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fset, InstEmit.FsetC, InstProps.Rd | InstProps.Ra | InstProps.Ps);
+ Add("010110111011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fsetp, InstEmit.FsetpR, InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
+ Add("0011011x1011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fsetp, InstEmit.FsetpI, InstProps.Ra | InstProps.Ib | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
+ Add("010010111011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fsetp, InstEmit.FsetpC, InstProps.Ra | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
Add("0101000011111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fswzadd, InstEmit.Fswzadd, InstProps.Rd | InstProps.Ra | InstProps.Rb);
Add("111000101100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Getcrsptr, InstEmit.Getcrsptr, InstProps.Rd | InstProps.NoPred);
Add("111000101101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Getlmembase, InstEmit.Getlmembase, InstProps.Rd | InstProps.NoPred);
@@ -133,12 +133,12 @@ namespace Ryujinx.Graphics.Shader.Decoders
Add("0111100x0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hmul2, InstEmit.Hmul2I, InstProps.Rd | InstProps.Ra | InstProps.Ib);
Add("0111100x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hmul2, InstEmit.Hmul2C, InstProps.Rd | InstProps.Ra);
Add("0010101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hmul232i, InstEmit.Hmul232i, InstProps.Rd | InstProps.Ra);
- Add("0101110100011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hset2, InstEmit.Hset2R, InstProps.Rd | InstProps.Ra | InstProps.Rb);
- Add("0111110x0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hset2, InstEmit.Hset2I, InstProps.Rd | InstProps.Ra | InstProps.Ib);
- Add("0111110x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hset2, InstEmit.Hset2C, InstProps.Rd | InstProps.Ra);
- Add("0101110100100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hsetp2, InstEmit.Hsetp2R, InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Pdn);
- Add("0111111x0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hsetp2, InstEmit.Hsetp2I, InstProps.Ra | InstProps.Ib | InstProps.Pd | InstProps.Pdn);
- Add("0111111x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hsetp2, InstEmit.Hsetp2C, InstProps.Ra | InstProps.Pd | InstProps.Pdn);
+ Add("0101110100011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hset2, InstEmit.Hset2R, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Ps);
+ Add("0111110x0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hset2, InstEmit.Hset2I, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Ps);
+ Add("0111110x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hset2, InstEmit.Hset2C, InstProps.Rd | InstProps.Ra | InstProps.Ps);
+ Add("0101110100100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hsetp2, InstEmit.Hsetp2R, InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
+ Add("0111111x0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hsetp2, InstEmit.Hsetp2I, InstProps.Ra | InstProps.Ib | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
+ Add("0111111x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hsetp2, InstEmit.Hsetp2C, InstProps.Ra | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
Add("0101110010111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.I2f, InstEmit.I2fR, InstProps.Rd | InstProps.Rb);
Add("0011100x10111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.I2f, InstEmit.I2fI, InstProps.Rd | InstProps.Ib);
Add("0100110010111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.I2f, InstEmit.I2fC, InstProps.Rd);
@@ -168,9 +168,9 @@ namespace Ryujinx.Graphics.Shader.Decoders
Add("0011010x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imadsp, InstEmit.ImadspI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Rc);
Add("010010101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imadsp, InstEmit.ImadspC, InstProps.Rd | InstProps.Ra | InstProps.Rc);
Add("010100101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imadsp, InstEmit.ImadspRc, InstProps.Rd | InstProps.Ra | InstProps.Rc);
- Add("0101110000100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imnmx, InstEmit.ImnmxR, InstProps.Rd | InstProps.Ra | InstProps.Rb);
- Add("0011100x00100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imnmx, InstEmit.ImnmxI, InstProps.Rd | InstProps.Ra | InstProps.Ib);
- Add("0100110000100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imnmx, InstEmit.ImnmxC, InstProps.Rd | InstProps.Ra);
+ Add("0101110000100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imnmx, InstEmit.ImnmxR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Ps);
+ Add("0011100x00100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imnmx, InstEmit.ImnmxI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Ps);
+ Add("0100110000100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imnmx, InstEmit.ImnmxC, InstProps.Rd | InstProps.Ra | InstProps.Ps);
Add("0101110000111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imul, InstEmit.ImulR, InstProps.Rd | InstProps.Ra | InstProps.Rb);
Add("0011100x00111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imul, InstEmit.ImulI, InstProps.Rd | InstProps.Ra | InstProps.Ib);
Add("0100110000111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imul, InstEmit.ImulC, InstProps.Rd | InstProps.Ra);
@@ -181,12 +181,12 @@ namespace Ryujinx.Graphics.Shader.Decoders
Add("0011100x00011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iscadd, InstEmit.IscaddI, InstProps.Rd | InstProps.Ra | InstProps.Ib);
Add("0100110000011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iscadd, InstEmit.IscaddC, InstProps.Rd | InstProps.Ra);
Add("000101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iscadd32i, InstEmit.Iscadd32i, InstProps.Rd | InstProps.Ra);
- Add("010110110101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iset, InstEmit.IsetR, InstProps.Rd | InstProps.Ra | InstProps.Rb);
- Add("0011011x0101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iset, InstEmit.IsetI, InstProps.Rd | InstProps.Ra | InstProps.Ib);
- Add("010010110101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iset, InstEmit.IsetC, InstProps.Rd | InstProps.Ra);
- Add("010110110110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Isetp, InstEmit.IsetpR, InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Pdn);
- Add("0011011x0110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Isetp, InstEmit.IsetpI, InstProps.Ra | InstProps.Ib | InstProps.Pd | InstProps.Pdn);
- Add("010010110110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Isetp, InstEmit.IsetpC, InstProps.Ra | InstProps.Pd | InstProps.Pdn);
+ Add("010110110101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iset, InstEmit.IsetR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Ps);
+ Add("0011011x0101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iset, InstEmit.IsetI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Ps);
+ Add("010010110101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iset, InstEmit.IsetC, InstProps.Rd | InstProps.Ra | InstProps.Ps);
+ Add("010110110110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Isetp, InstEmit.IsetpR, InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
+ Add("0011011x0110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Isetp, InstEmit.IsetpI, InstProps.Ra | InstProps.Ib | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
+ Add("010010110110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Isetp, InstEmit.IsetpC, InstProps.Ra | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
Add("111000100010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Jcal, InstEmit.Jcal, InstProps.Bra);
Add("111000100001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Jmp, InstEmit.Jmp, InstProps.Ra | InstProps.Bra);
Add("111000100000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Jmx, InstEmit.Jmx, InstProps.Ra | InstProps.Bra);
@@ -196,17 +196,17 @@ namespace Ryujinx.Graphics.Shader.Decoders
Add("1110111011010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ldg, InstEmit.Ldg, InstProps.Rd | InstProps.Ra);
Add("1110111101000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ldl, InstEmit.Ldl, InstProps.Rd | InstProps.Ra);
Add("1110111101001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lds, InstEmit.Lds, InstProps.Rd | InstProps.Ra);
- Add("0101101111010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lea, InstEmit.LeaR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Pd);
- Add("0011011x11010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lea, InstEmit.LeaI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Pd);
- Add("0100101111010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lea, InstEmit.LeaC, InstProps.Rd | InstProps.Ra | InstProps.Pd);
- Add("0101101111011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.LeaHi, InstEmit.LeaHiR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc | InstProps.Pd);
- Add("000110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.LeaHi, InstEmit.LeaHiC, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.Pd);
+ Add("0101101111010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lea, InstEmit.LeaR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.LPd);
+ Add("0011011x11010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lea, InstEmit.LeaI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.LPd);
+ Add("0100101111010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lea, InstEmit.LeaC, InstProps.Rd | InstProps.Ra | InstProps.LPd);
+ Add("0101101111011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.LeaHi, InstEmit.LeaHiR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc | InstProps.LPd);
+ Add("000110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.LeaHi, InstEmit.LeaHiC, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.LPd);
Add("0101000011010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lepc, InstEmit.Lepc);
Add("111000110001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Longjmp, InstEmit.Longjmp, InstProps.Bra);
- Add("0101110001000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lop, InstEmit.LopR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Pd);
- Add("0011100x01000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lop, InstEmit.LopI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Pd);
- Add("0100110001000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lop, InstEmit.LopC, InstProps.Rd | InstProps.Ra | InstProps.Pd);
- Add("0101101111100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lop3, InstEmit.Lop3R, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc | InstProps.Pd);
+ Add("0101110001000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lop, InstEmit.LopR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.LPd);
+ Add("0011100x01000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lop, InstEmit.LopI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.LPd);
+ Add("0100110001000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lop, InstEmit.LopC, InstProps.Rd | InstProps.Ra | InstProps.LPd);
+ Add("0101101111100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lop3, InstEmit.Lop3R, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc | InstProps.LPd);
Add("001111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lop3, InstEmit.Lop3I, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Rc);
Add("0000001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lop3, InstEmit.Lop3C, InstProps.Rd | InstProps.Ra | InstProps.Rc);
Add("000001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lop32i, InstEmit.Lop32i, InstProps.Rd | InstProps.Ra);
@@ -226,7 +226,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
Add("111000101010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Pbk, InstEmit.Pbk, InstProps.NoPred);
Add("111000101011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Pcnt, InstEmit.Pcnt, InstProps.NoPred);
Add("111000100011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Pexit, InstEmit.Pexit);
- Add("1110111111101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Pixld, InstEmit.Pixld, InstProps.Rd | InstProps.Ra);
+ Add("1110111111101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Pixld, InstEmit.Pixld, InstProps.Rd | InstProps.Ra | InstProps.VPd);
Add("111000101000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Plongjmp, InstEmit.Plongjmp, InstProps.Bra | InstProps.NoPred);
Add("0101110000001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Popc, InstEmit.PopcR, InstProps.Rd | InstProps.Rb);
Add("0011100x00001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Popc, InstEmit.PopcI, InstProps.Rd | InstProps.Ib);
@@ -236,14 +236,14 @@ namespace Ryujinx.Graphics.Shader.Decoders
Add("0011011x1100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Prmt, InstEmit.PrmtI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Rc);
Add("010010111100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Prmt, InstEmit.PrmtC, InstProps.Rd | InstProps.Ra | InstProps.Rc);
Add("010100111100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Prmt, InstEmit.PrmtRc, InstProps.Rd | InstProps.Ra | InstProps.Rc);
- Add("0101000010001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Pset, InstEmit.Pset, InstProps.Rd);
- Add("0101000010010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Psetp, InstEmit.Psetp, InstProps.Pd | InstProps.Pdn);
+ Add("0101000010001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Pset, InstEmit.Pset, InstProps.Rd | InstProps.Ps);
+ Add("0101000010010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Psetp, InstEmit.Psetp, InstProps.Pd | InstProps.Pdn | InstProps.Ps);
Add("1111000011000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.R2b, InstEmit.R2b, InstProps.Rb);
Add("0101110011110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.R2p, InstEmit.R2pR, InstProps.Ra | InstProps.Rb);
Add("0011100x11110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.R2p, InstEmit.R2pI, InstProps.Ra | InstProps.Ib);
Add("0100110011110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.R2p, InstEmit.R2pC, InstProps.Ra);
Add("111000111000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ram, InstEmit.Ram, InstProps.NoPred);
- Add("1110101111111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Red, InstEmit.Red, InstProps.Ra);
+ Add("1110101111111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Red, InstEmit.Red, InstProps.Ra | InstProps.Rb2);
Add("111000110010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ret, InstEmit.Ret, InstProps.Bra);
Add("0101110010010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Rro, InstEmit.RroR, InstProps.Rd | InstProps.Rb);
Add("0011100x10010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Rro, InstEmit.RroI, InstProps.Rd | InstProps.Ib);
@@ -251,16 +251,16 @@ namespace Ryujinx.Graphics.Shader.Decoders
Add("111000110110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Rtt, InstEmit.Rtt, InstProps.NoPred);
Add("1111000011001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.S2r, InstEmit.S2r, InstProps.Rd);
Add("111000110111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sam, InstEmit.Sam, InstProps.NoPred);
- Add("0101110010100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sel, InstEmit.SelR, InstProps.Rd | InstProps.Ra | InstProps.Rb);
- Add("0011100x10100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sel, InstEmit.SelI, InstProps.Rd | InstProps.Ra | InstProps.Ib);
- Add("0100110010100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sel, InstEmit.SelC, InstProps.Rd | InstProps.Ra);
+ Add("0101110010100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sel, InstEmit.SelR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Ps);
+ Add("0011100x10100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sel, InstEmit.SelI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Ps);
+ Add("0100110010100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sel, InstEmit.SelC, InstProps.Rd | InstProps.Ra | InstProps.Ps);
Add("111000101110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Setcrsptr, InstEmit.Setcrsptr, InstProps.Ra | InstProps.NoPred);
Add("111000101111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Setlmembase, InstEmit.Setlmembase, InstProps.Ra | InstProps.NoPred);
Add("0101101111111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Shf, InstEmit.ShfLR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc);
Add("0101110011111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Shf, InstEmit.ShfRR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc);
Add("0011011x11111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Shf, InstEmit.ShfLI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Rc);
Add("0011100x11111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Shf, InstEmit.ShfRI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Rc);
- Add("1110111100010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Shfl, InstEmit.Shfl, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc | InstProps.Pd);
+ Add("1110111100010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Shfl, InstEmit.Shfl, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc | InstProps.LPd);
Add("0101110001001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Shl, InstEmit.ShlR, InstProps.Rd | InstProps.Ra | InstProps.Rb);
Add("0011100x01001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Shl, InstEmit.ShlI, InstProps.Rd | InstProps.Ra | InstProps.Ib);
Add("0100110001001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Shl, InstEmit.ShlC, InstProps.Rd | InstProps.Ra);
@@ -276,12 +276,12 @@ namespace Ryujinx.Graphics.Shader.Decoders
Add("1110101001110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuatomB, InstEmit.SuatomB, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc);
Add("11101010x0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Suatom, InstEmit.Suatom, InstProps.Rd | InstProps.Ra | InstProps.Rb);
Add("1110101110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuatomB2, InstEmit.SuatomB2, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc);
- Add("1110101011010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuatomCasB, InstEmit.SuatomCasB, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc | InstProps.Pd2);
- Add("1110101x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuatomCas, InstEmit.SuatomCas, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Pd2);
- Add("111010110001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuldDB, InstEmit.SuldDB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.Pd2 | InstProps.TexB);
- Add("1110101100011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuldD, InstEmit.SuldD, InstProps.Rd | InstProps.Ra | InstProps.Pd2 | InstProps.Tex);
- Add("11101011000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuldB, InstEmit.SuldB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.Pd2 | InstProps.TexB);
- Add("11101011000x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Suld, InstEmit.Suld, InstProps.Rd | InstProps.Ra | InstProps.Pd2 | InstProps.Tex);
+ Add("1110101011010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuatomCasB, InstEmit.SuatomCasB, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc | InstProps.SPd);
+ Add("1110101x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuatomCas, InstEmit.SuatomCas, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.SPd);
+ Add("111010110001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuldDB, InstEmit.SuldDB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.SPd | InstProps.TexB);
+ Add("1110101100011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuldD, InstEmit.SuldD, InstProps.Rd | InstProps.Ra | InstProps.SPd | InstProps.Tex);
+ Add("11101011000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuldB, InstEmit.SuldB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.SPd | InstProps.TexB);
+ Add("11101011000x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Suld, InstEmit.Suld, InstProps.Rd | InstProps.Ra | InstProps.SPd | InstProps.Tex);
Add("111010110101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuredB, InstEmit.SuredB, InstProps.Rd | InstProps.Ra | InstProps.Rc);
Add("1110101101011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sured, InstEmit.Sured, InstProps.Rd | InstProps.Ra);
Add("111010110011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SustDB, InstEmit.SustDB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.TexB);
@@ -289,23 +289,23 @@ namespace Ryujinx.Graphics.Shader.Decoders
Add("11101011001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SustB, InstEmit.SustB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.TexB);
Add("11101011001x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sust, InstEmit.Sust, InstProps.Rd | InstProps.Ra | InstProps.Tex);
Add("1111000011111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sync, InstEmit.Sync, InstProps.Bra);
- Add("11000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tex, InstEmit.Tex, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Tex);
- Add("1101111010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.TexB, InstEmit.TexB, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.TexB);
+ Add("11000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tex, InstEmit.Tex, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.TPd | InstProps.Tex);
+ Add("1101111010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.TexB, InstEmit.TexB, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.TPd | InstProps.TexB);
Add("1101100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Texs, InstEmit.Texs, InstProps.Rd | InstProps.Rd2 | InstProps.Ra | InstProps.Rb | InstProps.Tex);
Add("1101000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.TexsF16, InstEmit.TexsF16, InstProps.Rd | InstProps.Rd2 | InstProps.Ra | InstProps.Rb | InstProps.Tex);
- Add("11011100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tld, InstEmit.Tld, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Tex);
- Add("11011101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.TldB, InstEmit.TldB, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.TexB);
+ Add("11011100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tld, InstEmit.Tld, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.TPd | InstProps.Tex);
+ Add("11011101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.TldB, InstEmit.TldB, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.TPd | InstProps.TexB);
Add("1101101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tlds, InstEmit.Tlds, InstProps.Rd | InstProps.Rd2 | InstProps.Ra | InstProps.Rb | InstProps.Tex);
Add("1101001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.TldsF16, InstEmit.TldsF16, InstProps.Rd | InstProps.Rd2 | InstProps.Ra | InstProps.Rb | InstProps.Tex);
- Add("110010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tld4, InstEmit.Tld4, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Tex);
- Add("1101111011xxxxxxxxxxxxx0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tld4B, InstEmit.Tld4B, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.TexB);
+ Add("110010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tld4, InstEmit.Tld4, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.TPd | InstProps.Tex);
+ Add("1101111011xxxxxxxxxxxxx0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tld4B, InstEmit.Tld4B, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.TPd | InstProps.TexB);
Add("1101111100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tld4s, InstEmit.Tld4s, InstProps.Rd | InstProps.Rd2 | InstProps.Ra | InstProps.Rb | InstProps.Tex);
Add("1101111110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tld4sF16, InstEmit.Tld4sF16, InstProps.Rd | InstProps.Rd2 | InstProps.Ra | InstProps.Rb | InstProps.Tex);
Add("1101111101011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tmml, InstEmit.Tmml, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Tex);
Add("1101111101100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.TmmlB, InstEmit.TmmlB, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.TexB);
Add("1101111101000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Txa, InstEmit.Txa, InstProps.Rd | InstProps.Ra | InstProps.Tex);
- Add("110111100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Txd, InstEmit.Txd, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Tex);
- Add("1101111001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.TxdB, InstEmit.TxdB, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.TexB);
+ Add("110111100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Txd, InstEmit.Txd, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.TPd | InstProps.Tex);
+ Add("1101111001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.TxdB, InstEmit.TxdB, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.TPd | InstProps.TexB);
Add("1101111101001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Txq, InstEmit.Txq, InstProps.Rd | InstProps.Ra | InstProps.Tex);
Add("1101111101010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.TxqB, InstEmit.TxqB, InstProps.Rd | InstProps.Ra | InstProps.TexB);
Add("01010100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Vabsdiff, InstEmit.Vabsdiff, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc);
@@ -313,10 +313,10 @@ namespace Ryujinx.Graphics.Shader.Decoders
Add("001000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Vadd, InstEmit.Vadd, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc);
Add("01011111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Vmad, InstEmit.Vmad, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc);
Add("0011101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Vmnmx, InstEmit.Vmnmx, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc);
- Add("0101000011011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Vote, InstEmit.Vote, InstProps.Rd);
+ Add("0101000011011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Vote, InstEmit.Vote, InstProps.Rd | InstProps.VPd | InstProps.Ps);
Add("0101000011100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Votevtg, InstEmit.Votevtg);
Add("0100000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Vset, InstEmit.Vset, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc);
- Add("0101000011110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Vsetp, InstEmit.Vsetp, InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Pdn);
+ Add("0101000011110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Vsetp, InstEmit.Vsetp, InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
Add("01010111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Vshl, InstEmit.Vshl, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc);
Add("01010110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Vshr, InstEmit.Vshr, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc);
Add("0101101100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Xmad, InstEmit.XmadR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc);
diff --git a/Ryujinx.Graphics.Shader/IGpuAccessor.cs b/Ryujinx.Graphics.Shader/IGpuAccessor.cs
index 3fdce8ea..a6ccdedd 100644
--- a/Ryujinx.Graphics.Shader/IGpuAccessor.cs
+++ b/Ryujinx.Graphics.Shader/IGpuAccessor.cs
@@ -61,6 +61,16 @@ namespace Ryujinx.Graphics.Shader
return 16;
}
+ bool QueryHostSupportsFragmentShaderInterlock()
+ {
+ return true;
+ }
+
+ bool QueryHostSupportsFragmentShaderOrderingIntel()
+ {
+ return false;
+ }
+
bool QueryHostSupportsImageLoadFormatted()
{
return true;
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs
index 33c1065a..c5a1e135 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs
@@ -56,14 +56,14 @@ namespace Ryujinx.Graphics.Shader.Instructions
public static void Cont(EmitterContext context)
{
- InstContUnsup op = context.GetOp();
+ InstCont op = context.GetOp();
context.Config.GpuAccessor.Log("Shader instruction ContUnsup is not implemented.");
}
public static void Cset(EmitterContext context)
{
- InstCsetUnsup op = context.GetOp();
+ InstCset op = context.GetOp();
context.Config.GpuAccessor.Log("Shader instruction CsetUnsup is not implemented.");
}
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitFlowControl.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitFlowControl.cs
index fce951ba..da34c1be 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitFlowControl.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitFlowControl.cs
@@ -67,7 +67,24 @@ namespace Ryujinx.Graphics.Shader.Instructions
{
InstCal op = context.GetOp();
- context.Call(context.GetFunctionId(context.CurrOp.GetAbsoluteAddress()), false);
+ 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 Exit(EmitterContext context)
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitSurface.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitSurface.cs
index f78f9db8..5959ac96 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitSurface.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitSurface.cs
@@ -109,28 +109,28 @@ namespace Ryujinx.Graphics.Shader.Instructions
{
InstSuldDB op = context.GetOp();
- EmitSuld(context, op.Dim, op.Size, 0, 0, op.SrcA, op.Dest, op.SrcC, useComponents: false, op.Ba, isBindless: true);
+ 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();
- EmitSuld(context, op.Dim, op.Size, op.TidB, 0, op.SrcA, op.Dest, 0, useComponents: false, op.Ba, isBindless: false);
+ 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();
- EmitSuld(context, op.Dim, 0, 0, op.Rgba, op.SrcA, op.Dest, 0, useComponents: true, false, isBindless: true);
+ EmitSuld(context, op.CacheOp, op.Dim, 0, 0, op.Rgba, op.SrcA, op.Dest, 0, useComponents: true, false, isBindless: true);
}
public static void Suld(EmitterContext context)
{
InstSuld op = context.GetOp();
- EmitSuld(context, op.Dim, 0, op.TidB, op.Rgba, op.SrcA, op.Dest, 0, useComponents: true, false, isBindless: false);
+ 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)
@@ -151,28 +151,28 @@ namespace Ryujinx.Graphics.Shader.Instructions
{
InstSustDB op = context.GetOp();
- EmitSust(context, op.Dim, op.Size, 0, 0, op.SrcA, op.Dest, op.SrcC, useComponents: false, op.Ba, isBindless: true);
+ 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();
- EmitSust(context, op.Dim, op.Size, op.TidB, 0, op.SrcA, op.Dest, 0, useComponents: false, op.Ba, isBindless: false);
+ 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();
- EmitSust(context, op.Dim, 0, 0, op.Rgba, op.SrcA, op.Dest, op.SrcC, useComponents: true, false, isBindless: true);
+ 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();
- EmitSust(context, op.Dim, 0, op.TidB, op.Rgba, op.SrcA, op.Dest, 0, useComponents: true, false, isBindless: false);
+ 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(
@@ -299,6 +299,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
private static void EmitSuld(
EmitterContext context,
+ CacheOpLd cacheOp,
SuDim dimensions,
SuSize size,
int imm,
@@ -363,6 +364,11 @@ namespace Ryujinx.Graphics.Shader.Instructions
TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None;
+ if (cacheOp == CacheOpLd.Cg)
+ {
+ flags |= TextureFlags.Coherent;
+ }
+
if (useComponents)
{
for (int compMask = (int)componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
@@ -546,6 +552,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
private static void EmitSust(
EmitterContext context,
+ CacheOpSt cacheOp,
SuDim dimensions,
SuSize size,
int imm,
@@ -654,6 +661,11 @@ namespace Ryujinx.Graphics.Shader.Instructions
TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None;
+ if (cacheOp == CacheOpSt.Cg)
+ {
+ flags |= TextureFlags.Coherent;
+ }
+
TextureOperation operation = context.CreateTextureOperation(
Instruction.ImageStore,
type,
diff --git a/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs b/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs
index e04e61a7..791c8f11 100644
--- a/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs
+++ b/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs
@@ -62,6 +62,8 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
EmitVertex,
EndPrimitive,
ExponentB2,
+ FSIBegin,
+ FSIEnd,
FindFirstSetS32,
FindFirstSetU32,
Floor,
diff --git a/Ryujinx.Graphics.Shader/IntermediateRepresentation/TextureFlags.cs b/Ryujinx.Graphics.Shader/IntermediateRepresentation/TextureFlags.cs
index 0cc938a3..6c20e856 100644
--- a/Ryujinx.Graphics.Shader/IntermediateRepresentation/TextureFlags.cs
+++ b/Ryujinx.Graphics.Shader/IntermediateRepresentation/TextureFlags.cs
@@ -14,6 +14,7 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
LodLevel = 1 << 5,
Offset = 1 << 6,
Offsets = 1 << 7,
+ Coherent = 1 << 8,
AtomicMask = 15 << 16,
diff --git a/Ryujinx.Graphics.Shader/StructuredIr/OperandInfo.cs b/Ryujinx.Graphics.Shader/StructuredIr/OperandInfo.cs
index e56008f0..34428815 100644
--- a/Ryujinx.Graphics.Shader/StructuredIr/OperandInfo.cs
+++ b/Ryujinx.Graphics.Shader/StructuredIr/OperandInfo.cs
@@ -21,6 +21,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
{
return type switch
{
+ OperandType.Argument => VariableType.S32,
OperandType.Attribute => VariableType.F32,
OperandType.AttributePerPatch => VariableType.F32,
OperandType.Constant => VariableType.S32,
diff --git a/Ryujinx.Graphics.Shader/TextureUsageFlags.cs b/Ryujinx.Graphics.Shader/TextureUsageFlags.cs
index 87be0d01..2419a1de 100644
--- a/Ryujinx.Graphics.Shader/TextureUsageFlags.cs
+++ b/Ryujinx.Graphics.Shader/TextureUsageFlags.cs
@@ -13,6 +13,7 @@ namespace Ryujinx.Graphics.Shader
// Integer sampled textures must be noted for resolution scaling.
ResScaleUnsupported = 1 << 0,
NeedsScaleValue = 1 << 1,
- ImageStore = 1 << 2
+ ImageStore = 1 << 2,
+ ImageCoherent = 1 << 3
}
}
diff --git a/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs b/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
index 6f2a6c3b..2f839b7a 100644
--- a/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
+++ b/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
@@ -10,24 +10,24 @@ namespace Ryujinx.Graphics.Shader.Translation
{
class EmitterContext
{
- public Block CurrBlock { get; set; }
- public InstOp CurrOp { get; set; }
-
+ public DecodedProgram Program { get; }
public ShaderConfig Config { get; }
public bool IsNonMain { get; }
+ public Block CurrBlock { get; set; }
+ public InstOp CurrOp { get; set; }
+
public int OperationsCount => _operations.Count;
- private readonly IReadOnlyDictionary _funcs;
private readonly List _operations;
private readonly Dictionary _labels;
- public EmitterContext(ShaderConfig config, bool isNonMain, IReadOnlyDictionary funcs)
+ public EmitterContext(DecodedProgram program, ShaderConfig config, bool isNonMain)
{
+ Program = program;
Config = config;
IsNonMain = isNonMain;
- _funcs = funcs;
_operations = new List();
_labels = new Dictionary();
}
@@ -154,11 +154,6 @@ namespace Ryujinx.Graphics.Shader.Translation
return label;
}
- public int GetFunctionId(ulong address)
- {
- return _funcs[address];
- }
-
public void PrepareForReturn()
{
if (!IsNonMain && Config.Stage == ShaderStage.Fragment)
@@ -195,7 +190,7 @@ namespace Ryujinx.Graphics.Shader.Translation
Operand isBgra = Attribute(AttributeConsts.FragmentOutputIsBgraBase + rtIndex * 4);
Operand lblIsBgra = Label();
- Operand lblEnd = Label();
+ Operand lblEnd = Label();
this.BranchIfTrue(lblIsBgra, isBgra);
diff --git a/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs b/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs
index a8fef95b..5e607b44 100644
--- a/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs
+++ b/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs
@@ -361,6 +361,16 @@ namespace Ryujinx.Graphics.Shader.Translation
return context.Add(Instruction.SwizzleAdd, Local(), a, b, Const(mask));
}
+ public static void FSIBegin(this EmitterContext context)
+ {
+ context.Add(Instruction.FSIBegin);
+ }
+
+ public static void FSIEnd(this EmitterContext context)
+ {
+ context.Add(Instruction.FSIEnd);
+ }
+
public static Operand GroupMemoryBarrier(this EmitterContext context)
{
return context.Add(Instruction.GroupMemoryBarrier);
diff --git a/Ryujinx.Graphics.Shader/Translation/FunctionMatch.cs b/Ryujinx.Graphics.Shader/Translation/FunctionMatch.cs
new file mode 100644
index 00000000..1c5d8c54
--- /dev/null
+++ b/Ryujinx.Graphics.Shader/Translation/FunctionMatch.cs
@@ -0,0 +1,866 @@
+using Ryujinx.Graphics.Shader.Decoders;
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+
+namespace Ryujinx.Graphics.Shader.Translation
+{
+ static class FunctionMatch
+ {
+ private static IPatternTreeNode[] _fsiGetAddressTree = PatternTrees.GetFsiGetAddress();
+ private static IPatternTreeNode[] _fsiGetAddressV2Tree = PatternTrees.GetFsiGetAddressV2();
+ private static IPatternTreeNode[] _fsiIsLastWarpThreadPatternTree = PatternTrees.GetFsiIsLastWarpThread();
+ private static IPatternTreeNode[] _fsiBeginPatternTree = PatternTrees.GetFsiBeginPattern();
+ private static IPatternTreeNode[] _fsiEndPatternTree = PatternTrees.GetFsiEndPattern();
+
+ public static void RunPass(DecodedProgram program)
+ {
+ byte[] externalRegs = new byte[4];
+ bool hasGetAddress = false;
+
+ foreach (DecodedFunction function in program)
+ {
+ if (function == program.MainFunction)
+ {
+ continue;
+ }
+
+ int externalReg4 = 0;
+
+ TreeNode[] functionTree = BuildTree(function.Blocks);
+
+ if (Matches(_fsiGetAddressTree, functionTree))
+ {
+ externalRegs[1] = functionTree[0].GetRd();
+ externalRegs[2] = functionTree[2].GetRd();
+ externalRegs[3] = functionTree[1].GetRd();
+ externalReg4 = functionTree[3].GetRd();
+ }
+ else if (Matches(_fsiGetAddressV2Tree, functionTree))
+ {
+ externalRegs[1] = functionTree[2].GetRd();
+ externalRegs[2] = functionTree[1].GetRd();
+ externalRegs[3] = functionTree[0].GetRd();
+ externalReg4 = functionTree[3].GetRd();
+ }
+
+ // Ensure the register allocation is valid.
+ // If so, then we have a match.
+ if (externalRegs[1] != externalRegs[2] &&
+ externalRegs[2] != externalRegs[3] &&
+ externalRegs[1] != externalRegs[3] &&
+ externalRegs[1] + 1 != externalRegs[2] &&
+ externalRegs[1] + 1 != externalRegs[3] &&
+ externalRegs[1] + 1 == externalReg4 &&
+ externalRegs[2] != RegisterConsts.RegisterZeroIndex &&
+ externalRegs[3] != RegisterConsts.RegisterZeroIndex &&
+ externalReg4 != RegisterConsts.RegisterZeroIndex)
+ {
+ hasGetAddress = true;
+ function.Type = FunctionType.Unused;
+ break;
+ }
+ }
+
+ foreach (DecodedFunction function in program)
+ {
+ if (function.IsCompilerGenerated || function == program.MainFunction)
+ {
+ continue;
+ }
+
+ if (hasGetAddress)
+ {
+ TreeNode[] functionTree = BuildTree(function.Blocks);
+
+ if (MatchesFsi(_fsiBeginPatternTree, program, function, functionTree, externalRegs))
+ {
+ function.Type = FunctionType.BuiltInFSIBegin;
+ continue;
+ }
+ else if (MatchesFsi(_fsiEndPatternTree, program, function, functionTree, externalRegs))
+ {
+ function.Type = FunctionType.BuiltInFSIEnd;
+ continue;
+ }
+ }
+ }
+ }
+
+ private struct TreeNodeUse
+ {
+ public TreeNode Node { get; }
+ public int Index { get; }
+ public bool Inverted { get; }
+
+ private TreeNodeUse(int index, bool inverted, TreeNode node)
+ {
+ Index = index;
+ Inverted = inverted;
+ Node = node;
+ }
+
+ public TreeNodeUse(int index, TreeNode node) : this(index, false, node)
+ {
+ }
+
+ public TreeNodeUse Flip()
+ {
+ return new TreeNodeUse(Index, !Inverted, Node);
+ }
+ }
+
+ private enum TreeNodeType : byte
+ {
+ Op,
+ Label
+ }
+
+ private class TreeNode
+ {
+ public readonly InstOp Op;
+ public readonly List Uses;
+ public TreeNodeType Type { get; }
+ public byte Order { get; }
+
+ public TreeNode(byte order)
+ {
+ Type = TreeNodeType.Label;
+ Order = order;
+ }
+
+ public TreeNode(InstOp op, byte order)
+ {
+ Op = op;
+ Uses = new List();
+ Type = TreeNodeType.Op;
+ Order = order;
+ }
+
+ public byte GetPd()
+ {
+ return (byte)((Op.RawOpCode >> 3) & 7);
+ }
+
+ public byte GetRd()
+ {
+ return (byte)Op.RawOpCode;
+ }
+ }
+
+ private static TreeNode[] BuildTree(Block[] blocks)
+ {
+ List nodes = new List();
+
+ Dictionary labels = new Dictionary();
+
+ TreeNodeUse[] predDefs = new TreeNodeUse[RegisterConsts.PredsCount];
+ TreeNodeUse[] gprDefs = new TreeNodeUse[RegisterConsts.GprsCount];
+
+ void DefPred(byte predIndex, int index, TreeNode node)
+ {
+ if (predIndex != RegisterConsts.PredicateTrueIndex)
+ {
+ predDefs[predIndex] = new TreeNodeUse(index, node);
+ }
+ }
+
+ void DefGpr(byte regIndex, int index, TreeNode node)
+ {
+ if (regIndex != RegisterConsts.RegisterZeroIndex)
+ {
+ gprDefs[regIndex] = new TreeNodeUse(index, node);
+ }
+ }
+
+ TreeNodeUse UsePred(byte predIndex, bool predInv)
+ {
+ if (predIndex != RegisterConsts.PredicateTrueIndex)
+ {
+ TreeNodeUse use = predDefs[predIndex];
+
+ if (use.Node != null)
+ {
+ nodes.Remove(use.Node);
+ }
+ else
+ {
+ use = new TreeNodeUse(-(predIndex + 2), null);
+ }
+
+ return predInv ? use.Flip() : use;
+ }
+
+ return new TreeNodeUse(-1, null);
+ }
+
+ TreeNodeUse UseGpr(byte regIndex)
+ {
+ if (regIndex != RegisterConsts.RegisterZeroIndex)
+ {
+ TreeNodeUse use = gprDefs[regIndex];
+
+ if (use.Node != null)
+ {
+ nodes.Remove(use.Node);
+ }
+ else
+ {
+ use = new TreeNodeUse(-(regIndex + 2), null);
+ }
+
+ return use;
+ }
+
+ return new TreeNodeUse(-1, null);
+ }
+
+ byte order = 0;
+
+ for (int index = 0; index < blocks.Length; index++)
+ {
+ Block block = blocks[index];
+
+ if (block.Predecessors.Count > 1)
+ {
+ TreeNode label = new TreeNode(order++);
+ nodes.Add(label);
+ labels.Add(block.Address, label);
+ }
+
+ for (int opIndex = 0; opIndex < block.OpCodes.Count; opIndex++)
+ {
+ InstOp op = block.OpCodes[opIndex];
+
+ TreeNode node = new TreeNode(op, IsOrderDependant(op.Name) ? order : (byte)0);
+
+ // Add uses.
+
+ if (!op.Props.HasFlag(InstProps.NoPred))
+ {
+ byte predIndex = (byte)((op.RawOpCode >> 16) & 7);
+ bool predInv = (op.RawOpCode & 0x80000) != 0;
+ node.Uses.Add(UsePred(predIndex, predInv));
+ }
+
+ if (op.Props.HasFlag(InstProps.Ps))
+ {
+ byte predIndex = (byte)((op.RawOpCode >> 39) & 7);
+ bool predInv = (op.RawOpCode & 0x40000000000) != 0;
+ node.Uses.Add(UsePred(predIndex, predInv));
+ }
+
+ if (op.Props.HasFlag(InstProps.Ra))
+ {
+ byte ra = (byte)(op.RawOpCode >> 8);
+ node.Uses.Add(UseGpr(ra));
+ }
+
+ if ((op.Props & (InstProps.Rb | InstProps.Rb2)) != 0)
+ {
+ byte rb = op.Props.HasFlag(InstProps.Rb2) ? (byte)op.RawOpCode : (byte)(op.RawOpCode >> 20);
+ node.Uses.Add(UseGpr(rb));
+ }
+
+ if (op.Props.HasFlag(InstProps.Rc))
+ {
+ byte rc = (byte)(op.RawOpCode >> 39);
+ node.Uses.Add(UseGpr(rc));
+ }
+
+ if (op.Name == InstName.Bra && labels.TryGetValue(op.GetAbsoluteAddress(), out TreeNode label))
+ {
+ node.Uses.Add(new TreeNodeUse(0, label));
+ }
+
+ // Make definitions.
+
+ int defIndex = 0;
+
+ InstProps pdType = op.Props & InstProps.PdMask;
+
+ if (pdType != 0)
+ {
+ int bit = pdType switch
+ {
+ InstProps.Pd => 3,
+ InstProps.LPd => 48,
+ InstProps.SPd => 30,
+ InstProps.TPd => 51,
+ InstProps.VPd => 45,
+ _ => throw new InvalidOperationException($"Table has unknown predicate destination {pdType}.")
+ };
+
+ byte predIndex = (byte)((op.RawOpCode >> bit) & 7);
+ DefPred(predIndex, defIndex++, node);
+ }
+
+ if (op.Props.HasFlag(InstProps.Rd))
+ {
+ byte rd = (byte)op.RawOpCode;
+ DefGpr(rd, defIndex++, node);
+ }
+
+ nodes.Add(node);
+ }
+ }
+
+ return nodes.ToArray();
+ }
+
+ private static bool IsOrderDependant(InstName name)
+ {
+ switch (name)
+ {
+ case InstName.Atom:
+ case InstName.AtomCas:
+ case InstName.Atoms:
+ case InstName.AtomsCas:
+ case InstName.Ld:
+ case InstName.Ldg:
+ case InstName.Ldl:
+ case InstName.Lds:
+ case InstName.Suatom:
+ case InstName.SuatomB:
+ case InstName.SuatomB2:
+ case InstName.SuatomCas:
+ case InstName.SuatomCasB:
+ case InstName.Suld:
+ case InstName.SuldB:
+ case InstName.SuldD:
+ case InstName.SuldDB:
+ return true;
+ }
+
+ return false;
+ }
+
+ private interface IPatternTreeNode
+ {
+ List Uses { get; }
+ InstName Name { get; }
+ TreeNodeType Type { get; }
+ byte Order { get; }
+ bool IsImm { get; }
+ bool Matches(in InstOp opInfo);
+ }
+
+ private struct PatternTreeNodeUse
+ {
+ public IPatternTreeNode Node { get; }
+ public int Index { get; }
+ public bool Inverted { get; }
+ public PatternTreeNodeUse Inv => new PatternTreeNodeUse(Index, !Inverted, Node);
+
+ private PatternTreeNodeUse(int index, bool inverted, IPatternTreeNode node)
+ {
+ Index = index;
+ Inverted = inverted;
+ Node = node;
+ }
+
+ public PatternTreeNodeUse(int index, IPatternTreeNode node) : this(index, false, node)
+ {
+ }
+ }
+
+ private class PatternTreeNode : IPatternTreeNode
+ {
+ public List Uses { get; }
+ private readonly Func _match;
+
+ public InstName Name { get; }
+ public TreeNodeType Type { get; }
+ public byte Order { get; }
+ public bool IsImm { get; }
+ public PatternTreeNodeUse Out => new PatternTreeNodeUse(0, this);
+
+ public PatternTreeNode(InstName name, Func match, TreeNodeType type = TreeNodeType.Op, byte order = 0, bool isImm = false)
+ {
+ Name = name;
+ _match = match;
+ Type = type;
+ Order = order;
+ IsImm = isImm;
+ Uses = new List();
+ }
+
+ public PatternTreeNode Use(PatternTreeNodeUse use)
+ {
+ Uses.Add(use);
+ return this;
+ }
+
+ public PatternTreeNodeUse OutAt(int index)
+ {
+ return new PatternTreeNodeUse(index, this);
+ }
+
+ public bool Matches(in InstOp opInfo)
+ {
+ if (opInfo.Name != Name)
+ {
+ return false;
+ }
+
+ ulong rawOp = opInfo.RawOpCode;
+ T op = Unsafe.As(ref rawOp);
+
+ if (!_match(op))
+ {
+ return false;
+ }
+
+ return true;
+ }
+ }
+
+ private static bool MatchesFsi(
+ IPatternTreeNode[] pattern,
+ DecodedProgram program,
+ DecodedFunction function,
+ TreeNode[] functionTree,
+ byte[] externalRegs)
+ {
+ if (function.Blocks.Length == 0)
+ {
+ return false;
+ }
+
+ InstOp callOp = function.Blocks[0].GetLastOp();
+
+ if (callOp.Name != InstName.Cal)
+ {
+ return false;
+ }
+
+ DecodedFunction callTarget = program.GetFunctionByAddress(callOp.GetAbsoluteAddress());
+ TreeNode[] callTargetTree = null;
+
+ if (callTarget == null || !Matches(_fsiIsLastWarpThreadPatternTree, callTargetTree = BuildTree(callTarget.Blocks)))
+ {
+ return false;
+ }
+
+ externalRegs[0] = callTargetTree[0].GetPd();
+
+ if (Matches(pattern, functionTree, externalRegs))
+ {
+ callTarget.RemoveCaller(function);
+ return true;
+ }
+
+ return false;
+ }
+
+ private static bool Matches(IPatternTreeNode[] pTree, TreeNode[] cTree, byte[] externalRegs = null)
+ {
+ if (pTree.Length != cTree.Length)
+ {
+ return false;
+ }
+
+ for (int index = 0; index < pTree.Length; index++)
+ {
+ if (!Matches(pTree[index], cTree[index], externalRegs))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static bool Matches(IPatternTreeNode pTreeNode, TreeNode cTreeNode, byte[] externalRegs)
+ {
+ if (!pTreeNode.Matches(in cTreeNode.Op) ||
+ pTreeNode.Type != cTreeNode.Type ||
+ pTreeNode.Order != cTreeNode.Order ||
+ pTreeNode.IsImm != cTreeNode.Op.Props.HasFlag(InstProps.Ib))
+ {
+ return false;
+ }
+
+ if (pTreeNode.Type == TreeNodeType.Op)
+ {
+ if (pTreeNode.Uses.Count != cTreeNode.Uses.Count)
+ {
+ return false;
+ }
+
+ for (int index = 0; index < pTreeNode.Uses.Count; index++)
+ {
+ var pUse = pTreeNode.Uses[index];
+ var cUse = cTreeNode.Uses[index];
+
+ if (pUse.Index <= -2)
+ {
+ if (externalRegs[-pUse.Index - 2] != (-cUse.Index - 2))
+ {
+ return false;
+ }
+ }
+ else if (pUse.Index != cUse.Index)
+ {
+ return false;
+ }
+
+ if (pUse.Inverted != cUse.Inverted || (pUse.Node == null) != (cUse.Node == null))
+ {
+ return false;
+ }
+
+ if (pUse.Node != null && !Matches(pUse.Node, cUse.Node, externalRegs))
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private static class PatternTrees
+ {
+ public static IPatternTreeNode[] GetFsiGetAddress()
+ {
+ var affinityValue = S2r(SReg.Affinity).Use(PT).Out;
+ var orderingTicketValue = S2r(SReg.OrderingTicket).Use(PT).Out;
+
+ return new IPatternTreeNode[]
+ {
+ Iscadd(cc: true, 2, 0, 404)
+ .Use(PT)
+ .Use(Iscadd(cc: false, 8)
+ .Use(PT)
+ .Use(Lop32i(LogicOp.And, 0xff)
+ .Use(PT)
+ .Use(affinityValue).Out)
+ .Use(Lop32i(LogicOp.And, 0xff)
+ .Use(PT)
+ .Use(orderingTicketValue).Out).Out),
+ ShrU32W(16)
+ .Use(PT)
+ .Use(orderingTicketValue),
+ Iadd32i(0x200)
+ .Use(PT)
+ .Use(Lop32i(LogicOp.And, 0xfe00)
+ .Use(PT)
+ .Use(orderingTicketValue).Out),
+ Iadd(x: true, 0, 405).Use(PT).Use(RZ),
+ Ret().Use(PT)
+ };
+ }
+
+ public static IPatternTreeNode[] GetFsiGetAddressV2()
+ {
+ var affinityValue = S2r(SReg.Affinity).Use(PT).Out;
+ var orderingTicketValue = S2r(SReg.OrderingTicket).Use(PT).Out;
+
+ return new IPatternTreeNode[]
+ {
+ ShrU32W(16)
+ .Use(PT)
+ .Use(orderingTicketValue),
+ Iadd32i(0x200)
+ .Use(PT)
+ .Use(Lop32i(LogicOp.And, 0xfe00)
+ .Use(PT)
+ .Use(orderingTicketValue).Out),
+ Iscadd(cc: true, 2, 0, 404)
+ .Use(PT)
+ .Use(Bfi(0x808)
+ .Use(PT)
+ .Use(affinityValue)
+ .Use(Lop32i(LogicOp.And, 0xff)
+ .Use(PT)
+ .Use(orderingTicketValue).Out).Out),
+ Iadd(x: true, 0, 405).Use(PT).Use(RZ),
+ Ret().Use(PT)
+ };
+ }
+
+ public static IPatternTreeNode[] GetFsiIsLastWarpThread()
+ {
+ var threadKillValue = S2r(SReg.ThreadKill).Use(PT).Out;
+ var laneIdValue = S2r(SReg.LaneId).Use(PT).Out;
+
+ return new IPatternTreeNode[]
+ {
+ IsetpU32(IComp.Eq)
+ .Use(PT)
+ .Use(PT)
+ .Use(FloU32()
+ .Use(PT)
+ .Use(Vote(VoteMode.Any)
+ .Use(PT)
+ .Use(IsetpU32(IComp.Ne)
+ .Use(PT)
+ .Use(PT)
+ .Use(Lop(negB: true, LogicOp.PassB)
+ .Use(PT)
+ .Use(RZ)
+ .Use(threadKillValue).OutAt(1))
+ .Use(RZ).Out).OutAt(1)).Out)
+ .Use(laneIdValue),
+ Ret().Use(PT)
+ };
+ }
+
+ public static IPatternTreeNode[] GetFsiBeginPattern()
+ {
+ var addressLowValue = CallArg(1);
+
+ static PatternTreeNodeUse HighU16Equals(PatternTreeNodeUse x)
+ {
+ var expectedValue = CallArg(3);
+
+ return IsetpU32(IComp.Eq)
+ .Use(PT)
+ .Use(PT)
+ .Use(ShrU32W(16).Use(PT).Use(x).Out)
+ .Use(expectedValue).Out;
+ }
+
+ PatternTreeNode label;
+
+ return new IPatternTreeNode[]
+ {
+ Cal(),
+ Ret().Use(CallArg(0).Inv),
+ Ret()
+ .Use(HighU16Equals(LdgE(CacheOpLd.Cg, LsSize.B32)
+ .Use(PT)
+ .Use(addressLowValue).Out)),
+ label = Label(),
+ Bra()
+ .Use(HighU16Equals(LdgE(CacheOpLd.Cg, LsSize.B32, 1)
+ .Use(PT)
+ .Use(addressLowValue).Out).Inv)
+ .Use(label.Out),
+ Ret().Use(PT)
+ };
+ }
+
+ public static IPatternTreeNode[] GetFsiEndPattern()
+ {
+ var voteResult = Vote(VoteMode.All).Use(PT).Use(PT).OutAt(1);
+ var popcResult = Popc().Use(PT).Use(voteResult).Out;
+ var threadKillValue = S2r(SReg.ThreadKill).Use(PT).Out;
+ var laneIdValue = S2r(SReg.LaneId).Use(PT).Out;
+
+ var addressLowValue = CallArg(1);
+ var incrementValue = CallArg(2);
+
+ return new IPatternTreeNode[]
+ {
+ Cal(),
+ Ret().Use(CallArg(0).Inv),
+ Membar(Decoders.Membar.Vc).Use(PT),
+ Ret().Use(IsetpU32(IComp.Ne)
+ .Use(PT)
+ .Use(PT)
+ .Use(threadKillValue)
+ .Use(RZ).Out),
+ RedE(RedOp.Add, AtomSize.U32)
+ .Use(IsetpU32(IComp.Eq)
+ .Use(PT)
+ .Use(PT)
+ .Use(FloU32()
+ .Use(PT)
+ .Use(voteResult).Out)
+ .Use(laneIdValue).Out)
+ .Use(addressLowValue)
+ .Use(Xmad(XmadCop.Cbcc, psl: true, hiloA: true, hiloB: true)
+ .Use(PT)
+ .Use(incrementValue)
+ .Use(Xmad(XmadCop.Cfull, mrg: true, hiloB: true)
+ .Use(PT)
+ .Use(incrementValue)
+ .Use(popcResult)
+ .Use(RZ).Out)
+ .Use(Xmad(XmadCop.Cfull)
+ .Use(PT)
+ .Use(incrementValue)
+ .Use(popcResult)
+ .Use(RZ).Out).Out),
+ Ret().Use(PT)
+ };
+ }
+
+ private static PatternTreeNode Bfi(int imm)
+ {
+ return new(InstName.Bfi, (op) => !op.WriteCC && op.Imm20 == imm, isImm: true);
+ }
+
+ private static PatternTreeNode Bra()
+ {
+ return new(InstName.Bra, (op) => op.Ccc == Ccc.T && !op.Ca);
+ }
+
+ private static PatternTreeNode Cal()
+ {
+ return new(InstName.Cal, (op) => !op.Ca && op.Inc);
+ }
+
+ private static PatternTreeNode FloU32()
+ {
+ return new(InstName.Flo, (op) => !op.Signed && !op.Sh && !op.NegB && !op.WriteCC);
+ }
+
+ private static PatternTreeNode Iadd(bool x, int cbufSlot, int cbufOffset)
+ {
+ return new(InstName.Iadd, (op) =>
+ !op.Sat &&
+ !op.WriteCC &&
+ op.X == x &&
+ op.AvgMode == AvgMode.NoNeg &&
+ op.CbufSlot == cbufSlot &&
+ op.CbufOffset == cbufOffset);
+ }
+
+ private static PatternTreeNode Iadd32i(int imm)
+ {
+ return new(InstName.Iadd32i, (op) => !op.Sat && !op.WriteCC && !op.X && op.AvgMode == AvgMode.NoNeg && op.Imm32 == imm);
+ }
+
+ private static PatternTreeNode Iscadd(bool cc, int imm)
+ {
+ return new(InstName.Iscadd, (op) => op.WriteCC == cc && op.AvgMode == AvgMode.NoNeg && op.Imm5 == imm);
+ }
+
+ private static PatternTreeNode Iscadd(bool cc, int imm, int cbufSlot, int cbufOffset)
+ {
+ return new(InstName.Iscadd, (op) =>
+ op.WriteCC == cc &&
+ op.AvgMode == AvgMode.NoNeg &&
+ op.Imm5 == imm &&
+ op.CbufSlot == cbufSlot &&
+ op.CbufOffset == cbufOffset);
+ }
+
+ private static PatternTreeNode IsetpU32(IComp comp)
+ {
+ return new(InstName.Isetp, (op) => !op.Signed && op.IComp == comp && op.Bop == BoolOp.And);
+ }
+
+ private static PatternTreeNode Label()
+ {
+ return new(InstName.Invalid, (op) => true, type: TreeNodeType.Label);
+ }
+
+ private static PatternTreeNode Lop(bool negB, LogicOp logicOp)
+ {
+ return new(InstName.Lop, (op) => !op.NegA && op.NegB == negB && !op.WriteCC && !op.X && op.Lop == logicOp && op.PredicateOp == PredicateOp.F);
+ }
+
+ private static PatternTreeNode Lop32i(LogicOp logicOp, int imm)
+ {
+ return new(InstName.Lop32i, (op) => !op.NegA && !op.NegB && !op.X && !op.WriteCC && op.LogicOp == logicOp && op.Imm32 == imm);
+ }
+
+ private static PatternTreeNode Membar(Membar membar)
+ {
+ return new(InstName.Membar, (op) => op.Membar == membar);
+ }
+
+ private static PatternTreeNode Popc()
+ {
+ return new(InstName.Popc, (op) => !op.NegB);
+ }
+
+ private static PatternTreeNode Ret()
+ {
+ return new(InstName.Ret, (op) => op.Ccc == Ccc.T);
+ }
+
+ private static PatternTreeNode S2r(SReg reg)
+ {
+ return new(InstName.S2r, (op) => op.SReg == reg);
+ }
+
+ private static PatternTreeNode ShrU32W(int imm)
+ {
+ return new(InstName.Shr, (op) => !op.Signed && !op.Brev && op.M && op.XMode == 0 && op.Imm20 == imm, isImm: true);
+ }
+
+ private static PatternTreeNode LdgE(CacheOpLd cacheOp, LsSize size, byte order = 0)
+ {
+ return new(InstName.Ldg, (op) => op.E && op.CacheOp == cacheOp && op.LsSize == size, order: order);
+ }
+
+ private static PatternTreeNode RedE(RedOp redOp, AtomSize size, byte order = 0)
+ {
+ return new(InstName.Red, (op) => op.E && op.RedOp == redOp && op.RedSize == size, order: order);
+ }
+
+ private static PatternTreeNode Vote(VoteMode mode)
+ {
+ return new(InstName.Vote, (op) => op.VoteMode == mode);
+ }
+
+ private static PatternTreeNode Xmad(XmadCop cop, bool psl = false, bool mrg = false, bool hiloA = false, bool hiloB = false)
+ {
+ return new(InstName.Xmad, (op) => op.XmadCop == cop && op.Psl == psl && op.Mrg == mrg && op.HiloA == hiloA && op.HiloB == hiloB);
+ }
+
+ private static PatternTreeNodeUse PT => PTOrRZ();
+ private static PatternTreeNodeUse RZ => PTOrRZ();
+ private static PatternTreeNodeUse Undef => new PatternTreeNodeUse(0, null);
+
+ private static PatternTreeNodeUse CallArg(int index)
+ {
+ return new PatternTreeNodeUse(-(index + 2), null);
+ }
+
+ private static PatternTreeNodeUse PTOrRZ()
+ {
+ return new PatternTreeNodeUse(-1, null);
+ }
+ }
+
+ private static void PrintTreeNode(TreeNode node, string indentation)
+ {
+ Console.WriteLine($" {node.Op.Name}");
+
+ for (int i = 0; i < node.Uses.Count; i++)
+ {
+ TreeNodeUse use = node.Uses[i];
+ bool last = i == node.Uses.Count - 1;
+ char separator = last ? '`' : '|';
+
+ if (use.Node != null)
+ {
+ Console.Write($"{indentation} {separator}- ({(use.Inverted ? "INV " : "")}{use.Index})");
+ PrintTreeNode(use.Node, indentation + (last ? " " : " | "));
+ }
+ else
+ {
+ Console.WriteLine($"{indentation} {separator}- ({(use.Inverted ? "INV " : "")}{use.Index}) NULL");
+ }
+ }
+ }
+
+ private static void PrintTreeNode(IPatternTreeNode node, string indentation)
+ {
+ Console.WriteLine($" {node.Name}");
+
+ for (int i = 0; i < node.Uses.Count; i++)
+ {
+ PatternTreeNodeUse use = node.Uses[i];
+ bool last = i == node.Uses.Count - 1;
+ char separator = last ? '`' : '|';
+
+ if (use.Node != null)
+ {
+ Console.Write($"{indentation} {separator}- ({(use.Inverted ? "INV " : "")}{use.Index})");
+ PrintTreeNode(use.Node, indentation + (last ? " " : " | "));
+ }
+ else
+ {
+ Console.WriteLine($"{indentation} {separator}- ({(use.Inverted ? "INV " : "")}{use.Index}) NULL");
+ }
+ }
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs b/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
index ec7e8982..2314016e 100644
--- a/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
+++ b/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
@@ -315,15 +315,16 @@ namespace Ryujinx.Graphics.Shader.Translation
bool isImage = inst == Instruction.ImageLoad || inst == Instruction.ImageStore || inst == Instruction.ImageAtomic;
bool isWrite = inst == Instruction.ImageStore || inst == Instruction.ImageAtomic;
bool accurateType = inst != Instruction.Lod;
+ bool coherent = flags.HasFlag(TextureFlags.Coherent);
if (isImage)
{
- SetUsedTextureOrImage(_usedImages, cbufSlot, handle, type, format, true, isWrite, false);
+ SetUsedTextureOrImage(_usedImages, cbufSlot, handle, type, format, true, isWrite, false, coherent);
}
else
{
bool intCoords = flags.HasFlag(TextureFlags.IntCoords) || inst == Instruction.TextureSize;
- SetUsedTextureOrImage(_usedTextures, cbufSlot, handle, type, TextureFormat.Unknown, intCoords, false, accurateType);
+ SetUsedTextureOrImage(_usedTextures, cbufSlot, handle, type, TextureFormat.Unknown, intCoords, false, accurateType, coherent);
}
}
@@ -335,7 +336,8 @@ namespace Ryujinx.Graphics.Shader.Translation
TextureFormat format,
bool intCoords,
bool write,
- bool accurateType)
+ bool accurateType,
+ bool coherent)
{
var dimensions = type.GetDimensions();
var isIndexed = type.HasFlag(SamplerType.Indexed);
@@ -361,6 +363,11 @@ namespace Ryujinx.Graphics.Shader.Translation
usageFlags |= TextureUsageFlags.ImageStore;
}
+ if (coherent)
+ {
+ usageFlags |= TextureUsageFlags.ImageCoherent;
+ }
+
int arraySize = isIndexed ? SamplerArraySize : 1;
for (int layer = 0; layer < arraySize; layer++)
diff --git a/Ryujinx.Graphics.Shader/Translation/Translator.cs b/Ryujinx.Graphics.Shader/Translation/Translator.cs
index 0243eba1..a658697b 100644
--- a/Ryujinx.Graphics.Shader/Translation/Translator.cs
+++ b/Ryujinx.Graphics.Shader/Translation/Translator.cs
@@ -4,7 +4,7 @@ using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.StructuredIr;
using Ryujinx.Graphics.Shader.Translation.Optimizations;
using System;
-using System.Collections.Generic;
+using System.Linq;
using System.Numerics;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
@@ -33,9 +33,7 @@ namespace Ryujinx.Graphics.Shader.Translation
{
counts ??= new TranslationCounts();
- Block[][] cfg = DecodeShader(address, gpuAccessor, options, counts, out ShaderConfig config);
-
- return new TranslatorContext(address, cfg, config);
+ return DecodeShader(address, gpuAccessor, options, counts);
}
internal static ShaderProgram Translate(FunctionCode[] functions, ShaderConfig config, out ShaderProgramInfo shaderProgramInfo)
@@ -112,35 +110,29 @@ namespace Ryujinx.Graphics.Shader.Translation
return program;
}
- private static Block[][] DecodeShader(
- ulong address,
- IGpuAccessor gpuAccessor,
- TranslationOptions options,
- TranslationCounts counts,
- out ShaderConfig config)
+ private static TranslatorContext DecodeShader(ulong address, IGpuAccessor gpuAccessor, TranslationOptions options, TranslationCounts counts)
{
- Block[][] cfg;
+ ShaderConfig config;
+ DecodedProgram program;
ulong maxEndAddress = 0;
if ((options.Flags & TranslationFlags.Compute) != 0)
{
config = new ShaderConfig(gpuAccessor, options, counts);
- cfg = Decoder.Decode(config, address);
+ program = Decoder.Decode(config, address);
}
else
{
config = new ShaderConfig(new ShaderHeader(gpuAccessor, address), gpuAccessor, options, counts);
- cfg = Decoder.Decode(config, address + HeaderSize);
+ program = Decoder.Decode(config, address + HeaderSize);
}
- for (int funcIndex = 0; funcIndex < cfg.Length; funcIndex++)
+ foreach (DecodedFunction function in program)
{
- for (int blkIndex = 0; blkIndex < cfg[funcIndex].Length; blkIndex++)
+ foreach (Block block in function.Blocks)
{
- Block block = cfg[funcIndex][blkIndex];
-
if (maxEndAddress < block.EndAddress)
{
maxEndAddress = block.EndAddress;
@@ -164,36 +156,36 @@ namespace Ryujinx.Graphics.Shader.Translation
config.SizeAdd((int)maxEndAddress + (options.Flags.HasFlag(TranslationFlags.Compute) ? 0 : HeaderSize));
- return cfg;
+ return new TranslatorContext(address, program, config);
}
- internal static FunctionCode[] EmitShader(Block[][] cfg, ShaderConfig config, bool initializeOutputs, out int initializationOperations)
+ internal static FunctionCode[] EmitShader(DecodedProgram program, ShaderConfig config, bool initializeOutputs, out int initializationOperations)
{
initializationOperations = 0;
- Dictionary funcIds = new Dictionary();
+ FunctionMatch.RunPass(program);
- for (int funcIndex = 0; funcIndex < cfg.Length; funcIndex++)
+ foreach (DecodedFunction function in program.OrderBy(x => x.Address).Where(x => !x.IsCompilerGenerated))
{
- funcIds.Add(cfg[funcIndex][0].Address, funcIndex);
+ program.AddFunctionAndSetId(function);
}
- List funcs = new List();
+ FunctionCode[] functions = new FunctionCode[program.FunctionsWithIdCount];
- for (int funcIndex = 0; funcIndex < cfg.Length; funcIndex++)
+ for (int index = 0; index < functions.Length; index++)
{
- EmitterContext context = new EmitterContext(config, funcIndex != 0, funcIds);
+ EmitterContext context = new EmitterContext(program, config, index != 0);
- if (initializeOutputs && funcIndex == 0)
+ if (initializeOutputs && index == 0)
{
EmitOutputsInitialization(context, config);
initializationOperations = context.OperationsCount;
}
- for (int blkIndex = 0; blkIndex < cfg[funcIndex].Length; blkIndex++)
- {
- Block block = cfg[funcIndex][blkIndex];
+ DecodedFunction function = program.GetFunctionById(index);
+ foreach (Block block in function.Blocks)
+ {
context.CurrBlock = block;
context.MarkLabel(context.GetLabel(block.Address));
@@ -201,10 +193,10 @@ namespace Ryujinx.Graphics.Shader.Translation
EmitOps(context, block);
}
- funcs.Add(new FunctionCode(context.GetOperations()));
+ functions[index] = new FunctionCode(context.GetOperations());
}
- return funcs.ToArray();
+ return functions;
}
private static void EmitOutputsInitialization(EmitterContext context, ShaderConfig config)
diff --git a/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs b/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs
index 34b116d6..b19e39af 100644
--- a/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs
+++ b/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs
@@ -9,7 +9,7 @@ namespace Ryujinx.Graphics.Shader.Translation
{
public class TranslatorContext
{
- private readonly Block[][] _cfg;
+ private readonly DecodedProgram _program;
private ShaderConfig _config;
public ulong Address { get; }
@@ -23,11 +23,11 @@ namespace Ryujinx.Graphics.Shader.Translation
public IGpuAccessor GpuAccessor => _config.GpuAccessor;
- internal TranslatorContext(ulong address, Block[][] cfg, ShaderConfig config)
+ internal TranslatorContext(ulong address, DecodedProgram program, ShaderConfig config)
{
Address = address;
+ _program = program;
_config = config;
- _cfg = cfg;
}
private static bool IsUserAttribute(Operand operand)
@@ -141,13 +141,13 @@ namespace Ryujinx.Graphics.Shader.Translation
nextStage._config.UsedInputAttributesPerPatch);
}
- FunctionCode[] code = EmitShader(_cfg, _config, initializeOutputs: other == null, out _);
+ FunctionCode[] code = EmitShader(_program, _config, initializeOutputs: other == null, out _);
if (other != null)
{
other._config.MergeOutputUserAttributes(_config.UsedOutputAttributes, 0);
- FunctionCode[] otherCode = EmitShader(other._cfg, other._config, initializeOutputs: true, out int aStart);
+ FunctionCode[] otherCode = EmitShader(other._program, other._config, initializeOutputs: true, out int aStart);
code = Combine(otherCode, code, aStart);