[Ryujinx.Graphics.Shader] Address dotnet-format issues (#5373)

* dotnet format style --severity info

Some changes were manually reverted.

* Restore a few unused methods and variables

* Silence dotnet format IDE0060 warnings

* Silence dotnet format IDE0052 warnings

* Silence dotnet format IDE0059 warnings

* Address or silence dotnet format CA1069 warnings

* Address or silence dotnet format CA2211 warnings

* Address review comments

* Fix formatting for switch expressions

* Address most dotnet format whitespace warnings

* Apply dotnet format whitespace formatting

A few of them have been manually reverted and the corresponding warning was silenced

* Format if-blocks correctly

* Run dotnet format whitespace after rebase

* Run dotnet format style after rebase

* Run dotnet format whitespace after rebase

* Run dotnet format style after rebase

* Run dotnet format after rebase and remove unused usings

- analyzers
- style
- whitespace

* Disable 'prefer switch expression' rule

* Add comments to disabled warnings

* Fix naming rule violation, Convert shader properties to auto-property and convert values to const

* Simplify properties and array initialization, Use const when possible, Remove trailing commas

* Run dotnet format after rebase

* Address IDE0251 warnings

* Address a few disabled IDE0060 warnings

* Silence IDE0060 in .editorconfig

* Run dotnet format after rebase

* Revert "Simplify properties and array initialization, Use const when possible, Remove trailing commas"

This reverts commit 9462e4136c0a2100dc28b20cf9542e06790aa67e.

* dotnet format whitespace after rebase

* First dotnet format pass

* Fix naming rule violations

* Add trailing commas

* Remove unused members and most unnecessary value assignments

* Remove more unnecessary assignments

* Remove NRE suppressor
This commit is contained in:
TSRBerry 2023-06-28 08:59:13 +02:00 committed by GitHub
parent e055217292
commit 9becbd7d72
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
162 changed files with 1611 additions and 1627 deletions

View file

@ -9,6 +9,6 @@ namespace Ryujinx.Graphics.Shader
Greater, Greater,
NotEqual, NotEqual,
GreaterOrEqual, GreaterOrEqual,
Always Always,
} }
} }

View file

@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.Shader
// Generic types. // Generic types.
Float, Float,
Sint, Sint,
Uint Uint,
} }
static class AttributeTypeExtensions static class AttributeTypeExtensions
@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.Shader
AttributeType.Float => "vec4", AttributeType.Float => "vec4",
AttributeType.Sint => "ivec4", AttributeType.Sint => "ivec4",
AttributeType.Uint => "uvec4", AttributeType.Uint => "uvec4",
_ => throw new ArgumentException($"Invalid attribute type \"{type}\".") _ => throw new ArgumentException($"Invalid attribute type \"{type}\"."),
}; };
} }
@ -31,7 +31,7 @@ namespace Ryujinx.Graphics.Shader
AttributeType.Float => AggregateType.FP32, AttributeType.Float => AggregateType.FP32,
AttributeType.Sint => AggregateType.S32, AttributeType.Sint => AggregateType.S32,
AttributeType.Uint => AggregateType.U32, AttributeType.Uint => AggregateType.U32,
_ => throw new ArgumentException($"Invalid attribute type \"{type}\".") _ => throw new ArgumentException($"Invalid attribute type \"{type}\"."),
}; };
} }
} }

View file

@ -13,6 +13,6 @@ namespace Ryujinx.Graphics.Shader
/// <summary> /// <summary>
/// Buffer is written to. /// Buffer is written to.
/// </summary> /// </summary>
Write = 1 << 0 Write = 1 << 0,
} }
} }

View file

@ -244,16 +244,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
} }
} }
private static string GetTfLayout(TransformFeedbackOutput tfOutput)
{
if (tfOutput.Valid)
{
return $"layout (xfb_buffer = {tfOutput.Buffer}, xfb_offset = {tfOutput.Offset}, xfb_stride = {tfOutput.Stride}) ";
}
return string.Empty;
}
public static void DeclareLocals(CodeGenContext context, StructuredFunction function) public static void DeclareLocals(CodeGenContext context, StructuredFunction function)
{ {
foreach (AstOperand decl in function.Locals) foreach (AstOperand decl in function.Locals)
@ -294,7 +284,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
AggregateType.Vector4 | AggregateType.FP64 => "dvec4", AggregateType.Vector4 | AggregateType.FP64 => "dvec4",
AggregateType.Vector4 | AggregateType.S32 => "ivec4", AggregateType.Vector4 | AggregateType.S32 => "ivec4",
AggregateType.Vector4 | AggregateType.U32 => "uvec4", AggregateType.Vector4 | AggregateType.U32 => "uvec4",
_ => throw new ArgumentException($"Invalid variable type \"{type}\".") _ => throw new ArgumentException($"Invalid variable type \"{type}\"."),
}; };
} }
@ -315,7 +305,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
string layout = buffer.Layout switch string layout = buffer.Layout switch
{ {
BufferLayout.Std140 => "std140", BufferLayout.Std140 => "std140",
_ => "std430" _ => "std430",
}; };
string set = string.Empty; string set = string.Empty;
@ -507,7 +497,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{ {
PixelImap.Constant => "flat ", PixelImap.Constant => "flat ",
PixelImap.ScreenLinear => "noperspective ", PixelImap.ScreenLinear => "noperspective ",
_ => string.Empty _ => string.Empty,
}; };
} }
@ -524,7 +514,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
2 => "vec2", 2 => "vec2",
3 => "vec3", 3 => "vec3",
4 => "vec4", 4 => "vec4",
_ => "float" _ => "float",
}; };
context.AppendLine($"layout (location = {attr}) in {type} {name};"); context.AppendLine($"layout (location = {attr}) in {type} {name};");
@ -611,7 +601,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
2 => "vec2", 2 => "vec2",
3 => "vec3", 3 => "vec3",
4 => "vec4", 4 => "vec4",
_ => "float" _ => "float",
}; };
string xfb = string.Empty; string xfb = string.Empty;
@ -647,7 +637,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{ {
AttributeType.Sint => "ivec4", AttributeType.Sint => "ivec4",
AttributeType.Uint => "uvec4", AttributeType.Uint => "uvec4",
_ => "vec4" _ => "vec4",
}; };
if (context.Config.GpuAccessor.QueryHostReducedPrecision() && context.Config.Stage == ShaderStage.Vertex && attr == 0) if (context.Config.GpuAccessor.QueryHostReducedPrecision() && context.Config.Stage == ShaderStage.Vertex && attr == 0)

View file

@ -13,7 +13,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
public static string Generate(StructuredProgramInfo info, ShaderConfig config) public static string Generate(StructuredProgramInfo info, ShaderConfig config)
{ {
CodeGenContext context = new CodeGenContext(info, config); CodeGenContext context = new(info, config);
Declarations.Declare(context, info); Declarations.Declare(context, info);
@ -74,7 +74,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
private static void PrintBlock(CodeGenContext context, AstBlock block, bool isMainFunction) private static void PrintBlock(CodeGenContext context, AstBlock block, bool isMainFunction)
{ {
AstBlockVisitor visitor = new AstBlockVisitor(block); AstBlockVisitor visitor = new(block);
visitor.BlockEntered += (sender, e) => visitor.BlockEntered += (sender, e) =>
{ {
@ -96,7 +96,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
context.AppendLine($"if ({GetCondExpr(context, e.Block.Condition)})"); context.AppendLine($"if ({GetCondExpr(context, e.Block.Condition)})");
break; break;
default: throw new InvalidOperationException($"Found unexpected block type \"{e.Block.Type}\"."); default:
throw new InvalidOperationException($"Found unexpected block type \"{e.Block.Type}\".");
} }
context.EnterScope(); context.EnterScope();

View file

@ -14,6 +14,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{ {
_infoTable = new InstInfo[(int)Instruction.Count]; _infoTable = new InstInfo[(int)Instruction.Count];
#pragma warning disable IDE0055 // Disable formatting
Add(Instruction.AtomicAdd, InstType.AtomicBinary, "atomicAdd"); Add(Instruction.AtomicAdd, InstType.AtomicBinary, "atomicAdd");
Add(Instruction.AtomicAnd, InstType.AtomicBinary, "atomicAnd"); Add(Instruction.AtomicAnd, InstType.AtomicBinary, "atomicAnd");
Add(Instruction.AtomicCompareAndSwap, InstType.AtomicTernary, "atomicCompSwap"); Add(Instruction.AtomicCompareAndSwap, InstType.AtomicTernary, "atomicCompSwap");
@ -125,6 +126,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
Add(Instruction.VoteAll, InstType.CallUnary, "allInvocationsARB"); Add(Instruction.VoteAll, InstType.CallUnary, "allInvocationsARB");
Add(Instruction.VoteAllEqual, InstType.CallUnary, "allInvocationsEqualARB"); Add(Instruction.VoteAllEqual, InstType.CallUnary, "allInvocationsEqualARB");
Add(Instruction.VoteAny, InstType.CallUnary, "anyInvocationARB"); Add(Instruction.VoteAny, InstType.CallUnary, "anyInvocationARB");
#pragma warning restore IDE0055
} }
private static void Add(Instruction inst, InstType flags, string opName = null, int precedence = 0) private static void Add(Instruction inst, InstType flags, string opName = null, int precedence = 0)
@ -163,7 +165,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{ {
// If the node isn't a operation, then it can only be a operand, // If the node isn't a operation, then it can only be a operand,
// and those never needs to be surrounded in parenthesis. // and those never needs to be surrounded in parenthesis.
if (!(node is AstOperation operation)) if (node is not AstOperation operation)
{ {
// This is sort of a special case, if this is a negative constant, // This is sort of a special case, if this is a negative constant,
// and it is consumed by a unary operation, we need to put on the parenthesis, // and it is consumed by a unary operation, we need to put on the parenthesis,
@ -208,7 +210,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
private static bool IsNegativeConst(IAstNode node) private static bool IsNegativeConst(IAstNode node)
{ {
if (!(node is AstOperand operand)) if (node is not AstOperand operand)
{ {
return false; return false;
} }

View file

@ -3,7 +3,6 @@ using Ryujinx.Graphics.Shader.StructuredIr;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using System; using System;
using System.Text; using System.Text;
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenHelper; using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenHelper;
using static Ryujinx.Graphics.Shader.StructuredIr.InstructionInfo; using static Ryujinx.Graphics.Shader.StructuredIr.InstructionInfo;
@ -49,7 +48,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
if (texOp.Inst == Instruction.ImageAtomic) if (texOp.Inst == Instruction.ImageAtomic)
{ {
texCallBuilder.Append((texOp.Flags & TextureFlags.AtomicMask) switch { texCallBuilder.Append((texOp.Flags & TextureFlags.AtomicMask) switch
{
#pragma warning disable IDE0055 // Disable formatting
TextureFlags.Add => "imageAtomicAdd", TextureFlags.Add => "imageAtomicAdd",
TextureFlags.Minimum => "imageAtomicMin", TextureFlags.Minimum => "imageAtomicMin",
TextureFlags.Maximum => "imageAtomicMax", TextureFlags.Maximum => "imageAtomicMax",
@ -61,6 +62,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
TextureFlags.Swap => "imageAtomicExchange", TextureFlags.Swap => "imageAtomicExchange",
TextureFlags.CAS => "imageAtomicCompSwap", TextureFlags.CAS => "imageAtomicCompSwap",
_ => "imageAtomicAdd", _ => "imageAtomicAdd",
#pragma warning restore IDE0055
}); });
} }
else else
@ -131,7 +133,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{ {
AggregateType.S32 => NumberFormatter.FormatInt(0), AggregateType.S32 => NumberFormatter.FormatInt(0),
AggregateType.U32 => NumberFormatter.FormatUint(0), AggregateType.U32 => NumberFormatter.FormatUint(0),
_ => NumberFormatter.FormatFloat(0) _ => NumberFormatter.FormatFloat(0),
}; };
} }
} }
@ -140,7 +142,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{ {
AggregateType.S32 => "i", AggregateType.S32 => "i",
AggregateType.U32 => "u", AggregateType.U32 => "u",
_ => string.Empty _ => string.Empty,
}; };
Append($"{prefix}vec4({string.Join(", ", cElems)})"); Append($"{prefix}vec4({string.Join(", ", cElems)})");
@ -159,7 +161,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{ {
TextureFlags.Increment => NumberFormatter.FormatInt(1, type), // TODO: Clamp value TextureFlags.Increment => NumberFormatter.FormatInt(1, type), // TODO: Clamp value
TextureFlags.Decrement => NumberFormatter.FormatInt(-1, type), // TODO: Clamp value TextureFlags.Decrement => NumberFormatter.FormatInt(-1, type), // TODO: Clamp value
_ => Src(type) _ => Src(type),
}; };
Append(value); Append(value);
@ -584,7 +586,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{ {
case StorageKind.ConstantBuffer: case StorageKind.ConstantBuffer:
case StorageKind.StorageBuffer: case StorageKind.StorageBuffer:
if (!(operation.GetSource(srcIndex++) is AstOperand bindingIndex) || bindingIndex.Type != OperandType.Constant) if (operation.GetSource(srcIndex++) is not AstOperand bindingIndex || bindingIndex.Type != OperandType.Constant)
{ {
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand."); throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
} }
@ -594,7 +596,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
? context.Config.Properties.ConstantBuffers[binding] ? context.Config.Properties.ConstantBuffers[binding]
: context.Config.Properties.StorageBuffers[binding]; : context.Config.Properties.StorageBuffers[binding];
if (!(operation.GetSource(srcIndex++) is AstOperand fieldIndex) || fieldIndex.Type != OperandType.Constant) if (operation.GetSource(srcIndex++) is not AstOperand fieldIndex || fieldIndex.Type != OperandType.Constant)
{ {
throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand."); throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand.");
} }
@ -606,7 +608,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
case StorageKind.LocalMemory: case StorageKind.LocalMemory:
case StorageKind.SharedMemory: case StorageKind.SharedMemory:
if (!(operation.GetSource(srcIndex++) is AstOperand bindingId) || bindingId.Type != OperandType.Constant) if (operation.GetSource(srcIndex++) is not AstOperand { Type: OperandType.Constant } bindingId)
{ {
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand."); throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
} }
@ -623,7 +625,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
case StorageKind.InputPerPatch: case StorageKind.InputPerPatch:
case StorageKind.Output: case StorageKind.Output:
case StorageKind.OutputPerPatch: case StorageKind.OutputPerPatch:
if (!(operation.GetSource(srcIndex++) is AstOperand varId) || varId.Type != OperandType.Constant) if (operation.GetSource(srcIndex++) is not AstOperand varId || varId.Type != OperandType.Constant)
{ {
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand."); throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
} }
@ -636,7 +638,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
if (context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput)) if (context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput))
{ {
if (!(operation.GetSource(srcIndex++) is AstOperand vecIndex) || vecIndex.Type != OperandType.Constant) if (operation.GetSource(srcIndex++) is not AstOperand vecIndex || vecIndex.Type != OperandType.Constant)
{ {
throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand."); throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand.");
} }

View file

@ -1,8 +1,10 @@
using System; using System;
using System.Diagnostics.CodeAnalysis;
namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{ {
[Flags] [Flags]
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
enum InstType enum InstType
{ {
OpNullary = Op | 0, OpNullary = Op | 0,
@ -28,6 +30,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
Atomic = 1 << 11, Atomic = 1 << 11,
Special = 1 << 12, Special = 1 << 12,
ArityMask = 0xff ArityMask = 0xff,
} }
} }

View file

@ -56,7 +56,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
IoVariable.VertexIndex => ("gl_VertexIndex", AggregateType.S32), IoVariable.VertexIndex => ("gl_VertexIndex", AggregateType.S32),
IoVariable.ViewportIndex => ("gl_ViewportIndex", AggregateType.S32), IoVariable.ViewportIndex => ("gl_ViewportIndex", AggregateType.S32),
IoVariable.ViewportMask => ("gl_ViewportMask", AggregateType.Array | AggregateType.S32), IoVariable.ViewportMask => ("gl_ViewportMask", AggregateType.Array | AggregateType.S32),
_ => (null, AggregateType.Invalid) _ => (null, AggregateType.Invalid),
}; };
} }

View file

@ -5,7 +5,6 @@ using Ryujinx.Graphics.Shader.Translation;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using static Ryujinx.Graphics.Shader.StructuredIr.InstructionInfo; using static Ryujinx.Graphics.Shader.StructuredIr.InstructionInfo;
namespace Ryujinx.Graphics.Shader.CodeGen.Glsl namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
@ -14,7 +13,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{ {
private static readonly string[] _stagePrefixes = new string[] { "cp", "vp", "tcp", "tep", "gp", "fp" }; private static readonly string[] _stagePrefixes = new string[] { "cp", "vp", "tcp", "tep", "gp", "fp" };
private Dictionary<AstOperand, string> _locals; private readonly Dictionary<AstOperand, string> _locals;
public OperandManager() public OperandManager()
{ {
@ -38,7 +37,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
OperandType.Constant => NumberFormatter.FormatInt(operand.Value), OperandType.Constant => NumberFormatter.FormatInt(operand.Value),
OperandType.LocalVariable => _locals[operand], OperandType.LocalVariable => _locals[operand],
OperandType.Undefined => DefaultNames.UndefinedName, OperandType.Undefined => DefaultNames.UndefinedName,
_ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\".") _ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\"."),
}; };
} }
@ -96,11 +95,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
return _stagePrefixes[index]; return _stagePrefixes[index];
} }
private static char GetSwizzleMask(int value)
{
return "xyzw"[value];
}
public static string GetArgumentName(int argIndex) public static string GetArgumentName(int argIndex)
{ {
return $"{DefaultNames.ArgumentNamePrefix}{argIndex}"; return $"{DefaultNames.ArgumentNamePrefix}{argIndex}";
@ -119,12 +113,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{ {
case StorageKind.ConstantBuffer: case StorageKind.ConstantBuffer:
case StorageKind.StorageBuffer: case StorageKind.StorageBuffer:
if (!(operation.GetSource(0) is AstOperand bindingIndex) || bindingIndex.Type != OperandType.Constant) if (operation.GetSource(0) is not AstOperand bindingIndex || bindingIndex.Type != OperandType.Constant)
{ {
throw new InvalidOperationException($"First input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand."); throw new InvalidOperationException($"First input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
} }
if (!(operation.GetSource(1) is AstOperand fieldIndex) || fieldIndex.Type != OperandType.Constant) if (operation.GetSource(1) is not AstOperand fieldIndex || fieldIndex.Type != OperandType.Constant)
{ {
throw new InvalidOperationException($"Second input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand."); throw new InvalidOperationException($"Second input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
} }
@ -138,7 +132,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
case StorageKind.LocalMemory: case StorageKind.LocalMemory:
case StorageKind.SharedMemory: case StorageKind.SharedMemory:
if (!(operation.GetSource(0) is AstOperand bindingId) || bindingId.Type != OperandType.Constant) if (operation.GetSource(0) is not AstOperand { Type: OperandType.Constant } bindingId)
{ {
throw new InvalidOperationException($"First input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand."); throw new InvalidOperationException($"First input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
} }
@ -153,7 +147,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
case StorageKind.InputPerPatch: case StorageKind.InputPerPatch:
case StorageKind.Output: case StorageKind.Output:
case StorageKind.OutputPerPatch: case StorageKind.OutputPerPatch:
if (!(operation.GetSource(0) is AstOperand varId) || varId.Type != OperandType.Constant) if (operation.GetSource(0) is not AstOperand varId || varId.Type != OperandType.Constant)
{ {
throw new InvalidOperationException($"First input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand."); throw new InvalidOperationException($"First input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
} }
@ -166,7 +160,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
if (context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput)) if (context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput))
{ {
if (!(operation.GetSource(1) is AstOperand vecIndex) || vecIndex.Type != OperandType.Constant) if (operation.GetSource(1) is not AstOperand vecIndex || vecIndex.Type != OperandType.Constant)
{ {
throw new InvalidOperationException($"Second input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand."); throw new InvalidOperationException($"Second input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
} }

View file

@ -38,18 +38,24 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{ {
switch (dstType) switch (dstType)
{ {
case AggregateType.Bool: return $"(floatBitsToInt({expr}) != 0)"; case AggregateType.Bool:
case AggregateType.S32: return $"floatBitsToInt({expr})"; return $"(floatBitsToInt({expr}) != 0)";
case AggregateType.U32: return $"floatBitsToUint({expr})"; case AggregateType.S32:
return $"floatBitsToInt({expr})";
case AggregateType.U32:
return $"floatBitsToUint({expr})";
} }
} }
else if (dstType == AggregateType.FP32) else if (dstType == AggregateType.FP32)
{ {
switch (srcType) switch (srcType)
{ {
case AggregateType.Bool: return $"intBitsToFloat({ReinterpretBoolToInt(expr, node, AggregateType.S32)})"; case AggregateType.Bool:
case AggregateType.S32: return $"intBitsToFloat({expr})"; return $"intBitsToFloat({ReinterpretBoolToInt(expr, node, AggregateType.S32)})";
case AggregateType.U32: return $"uintBitsToFloat({expr})"; case AggregateType.S32:
return $"intBitsToFloat({expr})";
case AggregateType.U32:
return $"uintBitsToFloat({expr})";
} }
} }
else if (srcType == AggregateType.Bool) else if (srcType == AggregateType.Bool)

View file

@ -1,13 +1,14 @@
using Ryujinx.Graphics.Shader.StructuredIr; using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.StructuredIr;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using Spv.Generator; using Spv.Generator;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using static Spv.Specification; using static Spv.Specification;
using Instruction = Spv.Generator.Instruction;
namespace Ryujinx.Graphics.Shader.CodeGen.Spirv namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
{ {
using IrConsts = IntermediateRepresentation.IrConsts;
using IrOperandType = IntermediateRepresentation.OperandType; using IrOperandType = IntermediateRepresentation.OperandType;
partial class CodeGenContext : Module partial class CodeGenContext : Module
@ -36,15 +37,15 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
public Dictionary<IoDefinition, Instruction> OutputsPerPatch { get; } = new Dictionary<IoDefinition, Instruction>(); public Dictionary<IoDefinition, Instruction> OutputsPerPatch { get; } = new Dictionary<IoDefinition, Instruction>();
public StructuredFunction CurrentFunction { get; set; } public StructuredFunction CurrentFunction { get; set; }
private readonly Dictionary<AstOperand, Instruction> _locals = new Dictionary<AstOperand, Instruction>(); private readonly Dictionary<AstOperand, Instruction> _locals = new();
private readonly Dictionary<int, Instruction[]> _localForArgs = new Dictionary<int, Instruction[]>(); private readonly Dictionary<int, Instruction[]> _localForArgs = new();
private readonly Dictionary<int, Instruction> _funcArgs = new Dictionary<int, Instruction>(); private readonly Dictionary<int, Instruction> _funcArgs = new();
private readonly Dictionary<int, (StructuredFunction, Instruction)> _functions = new Dictionary<int, (StructuredFunction, Instruction)>(); private readonly Dictionary<int, (StructuredFunction, Instruction)> _functions = new();
private class BlockState private class BlockState
{ {
private int _entryCount; private int _entryCount;
private readonly List<Instruction> _labels = new List<Instruction>(); private readonly List<Instruction> _labels = new();
public Instruction GetNextLabel(CodeGenContext context) public Instruction GetNextLabel(CodeGenContext context)
{ {
@ -67,7 +68,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
} }
} }
private readonly Dictionary<AstBlock, BlockState> _labels = new Dictionary<AstBlock, BlockState>(); private readonly Dictionary<AstBlock, BlockState> _labels = new();
public Dictionary<AstBlock, (Instruction, Instruction)> LoopTargets { get; set; } public Dictionary<AstBlock, (Instruction, Instruction)> LoopTargets { get; set; }
@ -98,7 +99,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
InputTopology.LinesAdjacency => 2, InputTopology.LinesAdjacency => 2,
InputTopology.Triangles => 3, InputTopology.Triangles => 3,
InputTopology.TrianglesAdjacency => 3, InputTopology.TrianglesAdjacency => 3,
_ => throw new InvalidOperationException($"Invalid input topology \"{inPrimitive}\".") _ => throw new InvalidOperationException($"Invalid input topology \"{inPrimitive}\"."),
}; };
} }
@ -222,7 +223,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
IrOperandType.Constant => GetConstant(type, operand), IrOperandType.Constant => GetConstant(type, operand),
IrOperandType.LocalVariable => GetLocal(type, operand), IrOperandType.LocalVariable => GetLocal(type, operand),
IrOperandType.Undefined => GetUndefined(type), IrOperandType.Undefined => GetUndefined(type),
_ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\".") _ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\"."),
}; };
} }
@ -259,7 +260,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
AggregateType.Bool => ConstantFalse(TypeBool()), AggregateType.Bool => ConstantFalse(TypeBool()),
AggregateType.FP32 => Constant(TypeFP32(), 0f), AggregateType.FP32 => Constant(TypeFP32(), 0f),
AggregateType.FP64 => Constant(TypeFP64(), 0d), AggregateType.FP64 => Constant(TypeFP64(), 0d),
_ => Constant(GetType(type), 0) _ => Constant(GetType(type), 0),
}; };
} }
@ -272,7 +273,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
AggregateType.FP64 => Constant(TypeFP64(), (double)BitConverter.Int32BitsToSingle(operand.Value)), AggregateType.FP64 => Constant(TypeFP64(), (double)BitConverter.Int32BitsToSingle(operand.Value)),
AggregateType.S32 => Constant(TypeS32(), operand.Value), AggregateType.S32 => Constant(TypeS32(), operand.Value),
AggregateType.U32 => Constant(TypeU32(), (uint)operand.Value), AggregateType.U32 => Constant(TypeU32(), (uint)operand.Value),
_ => throw new ArgumentException($"Invalid type \"{type}\".") _ => throw new ArgumentException($"Invalid type \"{type}\"."),
}; };
} }
@ -328,7 +329,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
AggregateType.Vector2 => 2, AggregateType.Vector2 => 2,
AggregateType.Vector3 => 3, AggregateType.Vector3 => 3,
AggregateType.Vector4 => 4, AggregateType.Vector4 => 4,
_ => 1 _ => 1,
}; };
return TypeVector(GetType(type & ~AggregateType.ElementCountMask), vectorLength); return TypeVector(GetType(type & ~AggregateType.ElementCountMask), vectorLength);
@ -342,7 +343,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
AggregateType.FP64 => TypeFP64(), AggregateType.FP64 => TypeFP64(),
AggregateType.S32 => TypeS32(), AggregateType.S32 => TypeS32(),
AggregateType.U32 => TypeU32(), AggregateType.U32 => TypeU32(),
_ => throw new ArgumentException($"Invalid attribute type \"{type}\".") _ => throw new ArgumentException($"Invalid attribute type \"{type}\"."),
}; };
} }

View file

@ -1,5 +1,4 @@
using Ryujinx.Common; using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.StructuredIr; using Ryujinx.Graphics.Shader.StructuredIr;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using Spv.Generator; using Spv.Generator;
@ -14,7 +13,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
{ {
static class Declarations static class Declarations
{ {
private static readonly string[] StagePrefixes = new string[] { "cp", "vp", "tcp", "tep", "gp", "fp" }; private static readonly string[] _stagePrefixes = { "cp", "vp", "tcp", "tep", "gp", "fp" };
public static void DeclareParameters(CodeGenContext context, StructuredFunction function) public static void DeclareParameters(CodeGenContext context, StructuredFunction function)
{ {
@ -107,7 +106,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
private static void DeclareBuffers(CodeGenContext context, IEnumerable<BufferDefinition> buffers, bool isBuffer) private static void DeclareBuffers(CodeGenContext context, IEnumerable<BufferDefinition> buffers, bool isBuffer)
{ {
HashSet<SpvInstruction> decoratedTypes = new HashSet<SpvInstruction>(); HashSet<SpvInstruction> decoratedTypes = new();
foreach (BufferDefinition buffer in buffers) foreach (BufferDefinition buffer in buffers)
{ {
@ -199,7 +198,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
SamplerType.Texture3D => Dim.Dim3D, SamplerType.Texture3D => Dim.Dim3D,
SamplerType.TextureCube => Dim.Cube, SamplerType.TextureCube => Dim.Cube,
SamplerType.TextureBuffer => Dim.Buffer, SamplerType.TextureBuffer => Dim.Buffer,
_ => throw new InvalidOperationException($"Invalid sampler type \"{descriptor.Type & SamplerType.Mask}\".") _ => throw new InvalidOperationException($"Invalid sampler type \"{descriptor.Type & SamplerType.Mask}\"."),
}; };
var imageType = context.TypeImage( var imageType = context.TypeImage(
@ -282,7 +281,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
SamplerType.Texture3D => Dim.Dim3D, SamplerType.Texture3D => Dim.Dim3D,
SamplerType.TextureCube => Dim.Cube, SamplerType.TextureCube => Dim.Cube,
SamplerType.TextureBuffer => Dim.Buffer, SamplerType.TextureBuffer => Dim.Buffer,
_ => throw new ArgumentException($"Invalid sampler type \"{type & SamplerType.Mask}\".") _ => throw new ArgumentException($"Invalid sampler type \"{type & SamplerType.Mask}\"."),
}; };
} }
@ -330,7 +329,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
TextureFormat.R10G10B10A2Unorm => ImageFormat.Rgb10A2, TextureFormat.R10G10B10A2Unorm => ImageFormat.Rgb10A2,
TextureFormat.R10G10B10A2Uint => ImageFormat.Rgb10a2ui, TextureFormat.R10G10B10A2Uint => ImageFormat.Rgb10a2ui,
TextureFormat.R11G11B10Float => ImageFormat.R11fG11fB10f, TextureFormat.R11G11B10Float => ImageFormat.R11fG11fB10f,
_ => throw new ArgumentException($"Invalid texture format \"{format}\".") _ => throw new ArgumentException($"Invalid texture format \"{format}\"."),
}; };
} }
@ -352,7 +351,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
(_, AggregateType varType) = IoMap.GetSpirvBuiltIn(ioVariable); (_, AggregateType varType) = IoMap.GetSpirvBuiltIn(ioVariable);
AggregateType elemType = varType & AggregateType.ElementTypeMask; AggregateType elemType = varType & AggregateType.ElementTypeMask;
if (elemType == AggregateType.S32 || elemType == AggregateType.U32) if (elemType is AggregateType.S32 or AggregateType.U32)
{ {
iq = PixelImap.Constant; iq = PixelImap.Constant;
} }
@ -410,7 +409,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
2 => AggregateType.Vector2, 2 => AggregateType.Vector2,
3 => AggregateType.Vector3, 3 => AggregateType.Vector3,
4 => AggregateType.Vector4, 4 => AggregateType.Vector4,
_ => AggregateType.Invalid _ => AggregateType.Invalid,
}; };
} }
@ -420,7 +419,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
if (!isPerPatch && IoMap.IsPerVertex(ioVariable, context.Config.Stage, isOutput)) if (!isPerPatch && IoMap.IsPerVertex(ioVariable, context.Config.Stage, isOutput))
{ {
int arraySize = context.Config.Stage == ShaderStage.Geometry ? context.InputVertices : 32; int arraySize = context.Config.Stage == ShaderStage.Geometry ? context.InputVertices : 32;
spvType = context.TypeArray(spvType, context.Constant(context.TypeU32(), (LiteralInteger)arraySize)); spvType = context.TypeArray(spvType, context.Constant(context.TypeU32(), arraySize));
if (context.Config.GpPassthrough && context.Config.GpuAccessor.QueryHostSupportsGeometryShaderPassthrough()) if (context.Config.GpPassthrough && context.Config.GpuAccessor.QueryHostSupportsGeometryShaderPassthrough())
{ {
@ -542,7 +541,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
private static string GetStagePrefix(ShaderStage stage) private static string GetStagePrefix(ShaderStage stage)
{ {
return StagePrefixes[(int)stage]; return _stagePrefixes[(int)stage];
} }
} }
} }

View file

@ -15,7 +15,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
ShaderStage.TessellationEvaluation => ExecutionModel.TessellationEvaluation, ShaderStage.TessellationEvaluation => ExecutionModel.TessellationEvaluation,
ShaderStage.Geometry => ExecutionModel.Geometry, ShaderStage.Geometry => ExecutionModel.Geometry,
ShaderStage.Fragment => ExecutionModel.Fragment, ShaderStage.Fragment => ExecutionModel.Fragment,
_ => throw new ArgumentException($"Invalid shader stage \"{stage}\".") _ => throw new ArgumentException($"Invalid shader stage \"{stage}\"."),
}; };
} }
} }

View file

@ -21,12 +21,13 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
MemorySemanticsMask.UniformMemory | MemorySemanticsMask.UniformMemory |
MemorySemanticsMask.AcquireRelease; MemorySemanticsMask.AcquireRelease;
private static readonly Func<CodeGenContext, AstOperation, OperationResult>[] InstTable; private static readonly Func<CodeGenContext, AstOperation, OperationResult>[] _instTable;
static Instructions() static Instructions()
{ {
InstTable = new Func<CodeGenContext, AstOperation, OperationResult>[(int)Instruction.Count]; _instTable = new Func<CodeGenContext, AstOperation, OperationResult>[(int)Instruction.Count];
#pragma warning disable IDE0055 // Disable formatting
Add(Instruction.Absolute, GenerateAbsolute); Add(Instruction.Absolute, GenerateAbsolute);
Add(Instruction.Add, GenerateAdd); Add(Instruction.Add, GenerateAdd);
Add(Instruction.AtomicAdd, GenerateAtomicAdd); Add(Instruction.AtomicAdd, GenerateAtomicAdd);
@ -141,16 +142,17 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
Add(Instruction.VoteAll, GenerateVoteAll); Add(Instruction.VoteAll, GenerateVoteAll);
Add(Instruction.VoteAllEqual, GenerateVoteAllEqual); Add(Instruction.VoteAllEqual, GenerateVoteAllEqual);
Add(Instruction.VoteAny, GenerateVoteAny); Add(Instruction.VoteAny, GenerateVoteAny);
#pragma warning restore IDE0055
} }
private static void Add(Instruction inst, Func<CodeGenContext, AstOperation, OperationResult> handler) private static void Add(Instruction inst, Func<CodeGenContext, AstOperation, OperationResult> handler)
{ {
InstTable[(int)(inst & Instruction.Mask)] = handler; _instTable[(int)(inst & Instruction.Mask)] = handler;
} }
public static OperationResult Generate(CodeGenContext context, AstOperation operation) public static OperationResult Generate(CodeGenContext context, AstOperation operation)
{ {
var handler = InstTable[(int)(operation.Inst & Instruction.Mask)]; var handler = _instTable[(int)(operation.Inst & Instruction.Mask)];
if (handler != null) if (handler != null)
{ {
return handler(context, operation); return handler(context, operation);
@ -305,7 +307,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
Debug.Assert(funcId.Type == OperandType.Constant); Debug.Assert(funcId.Type == OperandType.Constant);
(var function, var spvFunc) = context.GetFunction(funcId.Value); var (function, spvFunc) = context.GetFunction(funcId.Value);
var args = new SpvInstruction[operation.SourcesCount - 1]; var args = new SpvInstruction[operation.SourcesCount - 1];
var spvLocals = context.GetLocalForArgsPointers(funcId.Value); var spvLocals = context.GetLocalForArgsPointers(funcId.Value);
@ -625,11 +627,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
return context.Get(type, texOp.GetSource(srcIndex++)); return context.Get(type, texOp.GetSource(srcIndex++));
} }
SpvInstruction index = null;
if (isIndexed) if (isIndexed)
{ {
index = Src(AggregateType.S32); Src(AggregateType.S32);
} }
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.GetDimensions();
@ -657,9 +657,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
SpvInstruction value = Src(componentType); SpvInstruction value = Src(componentType);
(var imageType, var imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)]; (SpvInstruction imageType, SpvInstruction imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)];
var image = context.Load(imageType, imageVariable); context.Load(imageType, imageVariable);
SpvInstruction resultType = context.GetType(componentType); SpvInstruction resultType = context.GetType(componentType);
SpvInstruction imagePointerType = context.TypePointer(StorageClass.Image, resultType); SpvInstruction imagePointerType = context.TypePointer(StorageClass.Image, resultType);
@ -714,11 +714,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
return context.Get(type, texOp.GetSource(srcIndex++)); return context.Get(type, texOp.GetSource(srcIndex++));
} }
SpvInstruction index = null;
if (isIndexed) if (isIndexed)
{ {
index = Src(AggregateType.S32); Src(AggregateType.S32);
} }
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.GetDimensions();
@ -744,7 +742,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
pCoords = Src(AggregateType.S32); pCoords = Src(AggregateType.S32);
} }
(var imageType, var imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)]; var (imageType, imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)];
var image = context.Load(imageType, imageVariable); var image = context.Load(imageType, imageVariable);
var imageComponentType = context.GetType(componentType); var imageComponentType = context.GetType(componentType);
@ -778,11 +776,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
return context.Get(type, texOp.GetSource(srcIndex++)); return context.Get(type, texOp.GetSource(srcIndex++));
} }
SpvInstruction index = null;
if (isIndexed) if (isIndexed)
{ {
index = Src(AggregateType.S32); Src(AggregateType.S32);
} }
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.GetDimensions();
@ -833,7 +829,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
var texel = context.CompositeConstruct(context.TypeVector(context.GetType(componentType), ComponentsCount), cElems); var texel = context.CompositeConstruct(context.TypeVector(context.GetType(componentType), ComponentsCount), cElems);
(var imageType, var imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)]; var (imageType, imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)];
var image = context.Load(imageType, imageVariable); var image = context.Load(imageType, imageVariable);
@ -886,11 +882,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
return context.Get(type, texOp.GetSource(srcIndex++)); return context.Get(type, texOp.GetSource(srcIndex++));
} }
SpvInstruction index = null;
if (isIndexed) if (isIndexed)
{ {
index = Src(AggregateType.S32); Src(AggregateType.S32);
} }
int pCount = texOp.Type.GetDimensions(); int pCount = texOp.Type.GetDimensions();
@ -916,7 +910,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format); var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format);
(_, var sampledImageType, var sampledImageVariable) = context.Samplers[meta]; var (_, sampledImageType, sampledImageVariable) = context.Samplers[meta];
var image = context.Load(sampledImageType, sampledImageVariable); var image = context.Load(sampledImageType, sampledImageVariable);
@ -973,7 +967,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
loopBlock = loopBlock.Parent; loopBlock = loopBlock.Parent;
} }
(var loopTarget, var continueTarget) = context.LoopTargets[loopBlock]; (_, SpvInstruction continueTarget) = context.LoopTargets[loopBlock];
context.Branch(continueTarget); context.Branch(continueTarget);
@ -1307,11 +1301,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
return context.Get(type, texOp.GetSource(srcIndex++)); return context.Get(type, texOp.GetSource(srcIndex++));
} }
SpvInstruction index = null;
if (isIndexed) if (isIndexed)
{ {
index = Src(AggregateType.S32); Src(AggregateType.S32);
} }
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.GetDimensions();
@ -1395,7 +1387,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
derivatives = new[] derivatives = new[]
{ {
AssembleDerivativesVector(coordsCount), // dPdx AssembleDerivativesVector(coordsCount), // dPdx
AssembleDerivativesVector(coordsCount) // dPdy AssembleDerivativesVector(coordsCount), // dPdy
}; };
} }
@ -1445,7 +1437,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
AssembleOffsetVector(coordsCount), AssembleOffsetVector(coordsCount),
AssembleOffsetVector(coordsCount), AssembleOffsetVector(coordsCount),
AssembleOffsetVector(coordsCount), AssembleOffsetVector(coordsCount),
AssembleOffsetVector(coordsCount) AssembleOffsetVector(coordsCount),
}; };
} }
@ -1521,7 +1513,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format); var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format);
(var imageType, var sampledImageType, var sampledImageVariable) = context.Samplers[meta]; var (imageType, sampledImageType, sampledImageVariable) = context.Samplers[meta];
var image = context.Load(sampledImageType, sampledImageVariable); var image = context.Load(sampledImageType, sampledImageVariable);
@ -1595,16 +1587,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0; bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
SpvInstruction index = null;
if (isIndexed) if (isIndexed)
{ {
index = context.GetS32(texOp.GetSource(0)); context.GetS32(texOp.GetSource(0));
} }
var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format); var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format);
(var imageType, var sampledImageType, var sampledImageVariable) = context.Samplers[meta]; (SpvInstruction imageType, SpvInstruction sampledImageType, SpvInstruction sampledImageVariable) = context.Samplers[meta];
var image = context.Load(sampledImageType, sampledImageVariable); var image = context.Load(sampledImageType, sampledImageVariable);
image = context.Image(imageType, image); image = context.Image(imageType, image);
@ -1809,12 +1799,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
{ {
case StorageKind.ConstantBuffer: case StorageKind.ConstantBuffer:
case StorageKind.StorageBuffer: case StorageKind.StorageBuffer:
if (!(operation.GetSource(srcIndex++) is AstOperand bindingIndex) || bindingIndex.Type != OperandType.Constant) if (operation.GetSource(srcIndex++) is not AstOperand bindingIndex || bindingIndex.Type != OperandType.Constant)
{ {
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand."); throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
} }
if (!(operation.GetSource(srcIndex) is AstOperand fieldIndex) || fieldIndex.Type != OperandType.Constant) if (operation.GetSource(srcIndex) is not AstOperand fieldIndex || fieldIndex.Type != OperandType.Constant)
{ {
throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand."); throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand.");
} }
@ -1833,7 +1823,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
case StorageKind.LocalMemory: case StorageKind.LocalMemory:
case StorageKind.SharedMemory: case StorageKind.SharedMemory:
if (!(operation.GetSource(srcIndex++) is AstOperand bindingId) || bindingId.Type != OperandType.Constant) if (operation.GetSource(srcIndex++) is not AstOperand { Type: OperandType.Constant } bindingId)
{ {
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand."); throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
} }
@ -1856,7 +1846,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
case StorageKind.InputPerPatch: case StorageKind.InputPerPatch:
case StorageKind.Output: case StorageKind.Output:
case StorageKind.OutputPerPatch: case StorageKind.OutputPerPatch:
if (!(operation.GetSource(srcIndex++) is AstOperand varId) || varId.Type != OperandType.Constant) if (operation.GetSource(srcIndex++) is not AstOperand varId || varId.Type != OperandType.Constant)
{ {
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand."); throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
} }
@ -1869,7 +1859,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
if (context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput)) if (context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput))
{ {
if (!(operation.GetSource(srcIndex++) is AstOperand vecIndex) || vecIndex.Type != OperandType.Constant) if (operation.GetSource(srcIndex++) is not AstOperand vecIndex || vecIndex.Type != OperandType.Constant)
{ {
throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand."); throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand.");
} }
@ -1964,7 +1954,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
private static SpvInstruction GetScalarInput(CodeGenContext context, IoVariable ioVariable) private static SpvInstruction GetScalarInput(CodeGenContext context, IoVariable ioVariable)
{ {
(_, var varType) = IoMap.GetSpirvBuiltIn(ioVariable); var (_, varType) = IoMap.GetSpirvBuiltIn(ioVariable);
varType &= AggregateType.ElementTypeMask; varType &= AggregateType.ElementTypeMask;
var ioDefinition = new IoDefinition(StorageKind.Input, ioVariable); var ioDefinition = new IoDefinition(StorageKind.Input, ioVariable);

View file

@ -45,7 +45,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
IoVariable.VertexIndex => (BuiltIn.VertexIndex, AggregateType.S32), IoVariable.VertexIndex => (BuiltIn.VertexIndex, AggregateType.S32),
IoVariable.ViewportIndex => (BuiltIn.ViewportIndex, AggregateType.S32), IoVariable.ViewportIndex => (BuiltIn.ViewportIndex, AggregateType.S32),
IoVariable.ViewportMask => (BuiltIn.ViewportMaskNV, AggregateType.Array | AggregateType.S32), IoVariable.ViewportMask => (BuiltIn.ViewportMaskNV, AggregateType.Array | AggregateType.S32),
_ => (default, AggregateType.Invalid) _ => (default, AggregateType.Invalid),
}; };
} }
@ -58,7 +58,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
IoVariable.TessellationLevelOuter => 4, IoVariable.TessellationLevelOuter => 4,
IoVariable.ViewportMask => 1, IoVariable.ViewportMask => 1,
IoVariable.UserDefined => MaxAttributes, IoVariable.UserDefined => MaxAttributes,
_ => 1 _ => 1,
}; };
} }
@ -75,9 +75,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
case IoVariable.PointCoord: case IoVariable.PointCoord:
case IoVariable.ViewportMask: case IoVariable.ViewportMask:
return !isOutput && return !isOutput &&
(stage == ShaderStage.TessellationControl || stage is ShaderStage.TessellationControl or ShaderStage.TessellationEvaluation or ShaderStage.Geometry;
stage == ShaderStage.TessellationEvaluation ||
stage == ShaderStage.Geometry);
} }
return false; return false;

View file

@ -5,7 +5,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
{ {
readonly struct OperationResult readonly struct OperationResult
{ {
public static OperationResult Invalid => new OperationResult(AggregateType.Invalid, null); public static OperationResult Invalid => new(AggregateType.Invalid, null);
public AggregateType Type { get; } public AggregateType Type { get; }
public Instruction Value { get; } public Instruction Value { get; }

View file

@ -17,15 +17,15 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
{ {
// Resource pools for Spirv generation. Note: Increase count when more threads are being used. // Resource pools for Spirv generation. Note: Increase count when more threads are being used.
private const int GeneratorPoolCount = 1; private const int GeneratorPoolCount = 1;
private static ObjectPool<SpvInstructionPool> InstructionPool; private static readonly ObjectPool<SpvInstructionPool> _instructionPool;
private static ObjectPool<SpvLiteralIntegerPool> IntegerPool; private static readonly ObjectPool<SpvLiteralIntegerPool> _integerPool;
private static object PoolLock; private static readonly object _poolLock;
static SpirvGenerator() static SpirvGenerator()
{ {
InstructionPool = new (() => new SpvInstructionPool(), GeneratorPoolCount); _instructionPool = new(() => new SpvInstructionPool(), GeneratorPoolCount);
IntegerPool = new (() => new SpvLiteralIntegerPool(), GeneratorPoolCount); _integerPool = new(() => new SpvLiteralIntegerPool(), GeneratorPoolCount);
PoolLock = new object(); _poolLock = new object();
} }
private const HelperFunctionsMask NeedsInvocationIdMask = private const HelperFunctionsMask NeedsInvocationIdMask =
@ -40,13 +40,13 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
SpvInstructionPool instPool; SpvInstructionPool instPool;
SpvLiteralIntegerPool integerPool; SpvLiteralIntegerPool integerPool;
lock (PoolLock) lock (_poolLock)
{ {
instPool = InstructionPool.Allocate(); instPool = _instructionPool.Allocate();
integerPool = IntegerPool.Allocate(); integerPool = _integerPool.Allocate();
} }
CodeGenContext context = new CodeGenContext(info, config, instPool, integerPool); CodeGenContext context = new(info, config, instPool, integerPool);
context.AddCapability(Capability.GroupNonUniformBallot); context.AddCapability(Capability.GroupNonUniformBallot);
context.AddCapability(Capability.GroupNonUniformShuffle); context.AddCapability(Capability.GroupNonUniformShuffle);
@ -133,10 +133,10 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
byte[] result = context.Generate(); byte[] result = context.Generate();
lock (PoolLock) lock (_poolLock)
{ {
InstructionPool.Release(instPool); _instructionPool.Release(instPool);
IntegerPool.Release(integerPool); _integerPool.Release(integerPool);
} }
return result; return result;
@ -144,7 +144,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
private static void Generate(CodeGenContext context, StructuredProgramInfo info, int funcIndex) private static void Generate(CodeGenContext context, StructuredProgramInfo info, int funcIndex)
{ {
(var function, var spvFunc) = context.GetFunction(funcIndex); var (function, spvFunc) = context.GetFunction(funcIndex);
context.CurrentFunction = function; context.CurrentFunction = function;
context.AddFunction(spvFunc); context.AddFunction(spvFunc);
@ -160,7 +160,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
Generate(context, function.MainBlock); Generate(context, function.MainBlock);
// Functions must always end with a return. // Functions must always end with a return.
if (!(function.MainBlock.Last is AstOperation operation) || if (function.MainBlock.Last is not AstOperation operation ||
(operation.Inst != Instruction.Return && operation.Inst != Instruction.Discard)) (operation.Inst != Instruction.Return && operation.Inst != Instruction.Discard))
{ {
context.Return(); context.Return();
@ -232,7 +232,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
InputTopology.LinesAdjacency => ExecutionMode.InputLinesAdjacency, InputTopology.LinesAdjacency => ExecutionMode.InputLinesAdjacency,
InputTopology.Triangles => ExecutionMode.Triangles, InputTopology.Triangles => ExecutionMode.Triangles,
InputTopology.TrianglesAdjacency => ExecutionMode.InputTrianglesAdjacency, InputTopology.TrianglesAdjacency => ExecutionMode.InputTrianglesAdjacency,
_ => throw new InvalidOperationException($"Invalid input topology \"{inputTopology}\".") _ => throw new InvalidOperationException($"Invalid input topology \"{inputTopology}\"."),
}); });
context.AddExecutionMode(spvFunc, ExecutionMode.Invocations, (SpvLiteralInteger)context.Config.ThreadsPerInputPrimitive); context.AddExecutionMode(spvFunc, ExecutionMode.Invocations, (SpvLiteralInteger)context.Config.ThreadsPerInputPrimitive);
@ -242,7 +242,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
OutputTopology.PointList => ExecutionMode.OutputPoints, OutputTopology.PointList => ExecutionMode.OutputPoints,
OutputTopology.LineStrip => ExecutionMode.OutputLineStrip, OutputTopology.LineStrip => ExecutionMode.OutputLineStrip,
OutputTopology.TriangleStrip => ExecutionMode.OutputTriangleStrip, OutputTopology.TriangleStrip => ExecutionMode.OutputTriangleStrip,
_ => throw new InvalidOperationException($"Invalid output topology \"{context.Config.OutputTopology}\".") _ => throw new InvalidOperationException($"Invalid output topology \"{context.Config.OutputTopology}\"."),
}); });
int maxOutputVertices = context.Config.GpPassthrough ? context.InputVertices : context.Config.MaxOutputVertices; int maxOutputVertices = context.Config.GpPassthrough ? context.InputVertices : context.Config.MaxOutputVertices;
@ -294,7 +294,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
private static void Generate(CodeGenContext context, AstBlock block) private static void Generate(CodeGenContext context, AstBlock block)
{ {
AstBlockVisitor visitor = new AstBlockVisitor(block); AstBlockVisitor visitor = new(block);
var loopTargets = new Dictionary<AstBlock, (SpvInstruction, SpvInstruction)>(); var loopTargets = new Dictionary<AstBlock, (SpvInstruction, SpvInstruction)>();
@ -346,7 +346,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
// if the condition is true. // if the condition is true.
AstBlock mergeBlock = e.Block.Parent; AstBlock mergeBlock = e.Block.Parent;
(var loopTarget, var continueTarget) = loopTargets[e.Block]; var (loopTarget, continueTarget) = loopTargets[e.Block];
context.Branch(continueTarget); context.Branch(continueTarget);
context.AddLabel(continueTarget); context.AddLabel(continueTarget);

View file

@ -148,7 +148,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
{ {
if (OpCodes.Count != 0) if (OpCodes.Count != 0)
{ {
return OpCodes[OpCodes.Count - 1]; return OpCodes[^1];
} }
return default; return default;

View file

@ -3,7 +3,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
namespace Ryujinx.Graphics.Shader.Decoders namespace Ryujinx.Graphics.Shader.Decoders
@ -12,8 +11,8 @@ namespace Ryujinx.Graphics.Shader.Decoders
{ {
public static DecodedProgram Decode(ShaderConfig config, ulong startAddress) public static DecodedProgram Decode(ShaderConfig config, ulong startAddress)
{ {
Queue<DecodedFunction> functionsQueue = new Queue<DecodedFunction>(); Queue<DecodedFunction> functionsQueue = new();
Dictionary<ulong, DecodedFunction> functionsVisited = new Dictionary<ulong, DecodedFunction>(); Dictionary<ulong, DecodedFunction> functionsVisited = new();
DecodedFunction EnqueueFunction(ulong address) DecodedFunction EnqueueFunction(ulong address)
{ {
@ -30,9 +29,9 @@ namespace Ryujinx.Graphics.Shader.Decoders
while (functionsQueue.TryDequeue(out DecodedFunction currentFunction)) while (functionsQueue.TryDequeue(out DecodedFunction currentFunction))
{ {
List<Block> blocks = new List<Block>(); List<Block> blocks = new();
Queue<Block> workQueue = new Queue<Block>(); Queue<Block> workQueue = new();
Dictionary<ulong, Block> visited = new Dictionary<ulong, Block>(); Dictionary<ulong, Block> visited = new();
Block GetBlock(ulong blkAddress) Block GetBlock(ulong blkAddress)
{ {
@ -273,12 +272,12 @@ namespace Ryujinx.Graphics.Shader.Decoders
int offset; int offset;
int count = 1; int count = 1;
bool isStore = false; bool isStore = false;
bool indexed = false; bool indexed;
bool perPatch = false; bool perPatch = false;
if (name == InstName.Ast) if (name == InstName.Ast)
{ {
InstAst opAst = new InstAst(opCode); InstAst opAst = new(opCode);
count = (int)opAst.AlSize + 1; count = (int)opAst.AlSize + 1;
offset = opAst.Imm11; offset = opAst.Imm11;
indexed = opAst.Phys; indexed = opAst.Phys;
@ -287,7 +286,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
} }
else if (name == InstName.Ald) else if (name == InstName.Ald)
{ {
InstAld opAld = new InstAld(opCode); InstAld opAld = new(opCode);
count = (int)opAld.AlSize + 1; count = (int)opAld.AlSize + 1;
offset = opAld.Imm11; offset = opAld.Imm11;
indexed = opAld.Phys; indexed = opAld.Phys;
@ -296,7 +295,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
} }
else /* if (name == InstName.Ipa) */ else /* if (name == InstName.Ipa) */
{ {
InstIpa opIpa = new InstIpa(opCode); InstIpa opIpa = new(opCode);
offset = opIpa.Imm10; offset = opIpa.Imm10;
indexed = opIpa.Idx; indexed = opIpa.Idx;
} }
@ -370,7 +369,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
private static bool IsUnconditional(ref InstOp op) private static bool IsUnconditional(ref InstOp op)
{ {
InstConditional condOp = new InstConditional(op.RawOpCode); InstConditional condOp = new(op.RawOpCode);
if ((op.Name == InstName.Bra || op.Name == InstName.Exit) && condOp.Ccc != Ccc.T) if ((op.Name == InstName.Bra || op.Name == InstName.Exit) && condOp.Ccc != Ccc.T)
{ {
@ -391,9 +390,9 @@ namespace Ryujinx.Graphics.Shader.Decoders
if (lastOp.Name == InstName.Brx && block.Successors.Count == (hasNext ? 1 : 0)) if (lastOp.Name == InstName.Brx && block.Successors.Count == (hasNext ? 1 : 0))
{ {
HashSet<ulong> visited = new HashSet<ulong>(); HashSet<ulong> visited = new();
InstBrx opBrx = new InstBrx(lastOp.RawOpCode); InstBrx opBrx = new(lastOp.RawOpCode);
ulong baseOffset = lastOp.GetAbsoluteAddress(); ulong baseOffset = lastOp.GetAbsoluteAddress();
// An indirect branch could go anywhere, // An indirect branch could go anywhere,
@ -437,7 +436,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
// On a successful match, "BaseOffset" is the offset in bytes where the jump offsets are // On a successful match, "BaseOffset" is the offset in bytes where the jump offsets are
// located on the constant buffer, and "UpperBound" is the total number of offsets for the BRX, minus 1. // located on the constant buffer, and "UpperBound" is the total number of offsets for the BRX, minus 1.
HashSet<Block> visited = new HashSet<Block>(); HashSet<Block> visited = new();
var ldcLocation = FindFirstRegWrite(visited, new BlockLocation(block, block.OpCodes.Count - 1), brxReg); var ldcLocation = FindFirstRegWrite(visited, new BlockLocation(block, block.OpCodes.Count - 1), brxReg);
if (ldcLocation.Block == null || ldcLocation.Block.OpCodes[ldcLocation.Index].Name != InstName.Ldc) if (ldcLocation.Block == null || ldcLocation.Block.OpCodes[ldcLocation.Index].Name != InstName.Ldc)
@ -507,7 +506,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
private static BlockLocation FindFirstRegWrite(HashSet<Block> visited, BlockLocation location, int regIndex) private static BlockLocation FindFirstRegWrite(HashSet<Block> visited, BlockLocation location, int regIndex)
{ {
Queue<BlockLocation> toVisit = new Queue<BlockLocation>(); Queue<BlockLocation> toVisit = new();
toVisit.Enqueue(location); toVisit.Enqueue(location);
visited.Add(location.Block); visited.Add(location.Block);
@ -554,10 +553,10 @@ namespace Ryujinx.Graphics.Shader.Decoders
{ {
Brk, Brk,
Cont, Cont,
Sync Sync,
} }
private struct PathBlockState private readonly struct PathBlockState
{ {
public Block Block { get; } public Block Block { get; }
@ -565,13 +564,13 @@ namespace Ryujinx.Graphics.Shader.Decoders
{ {
None, None,
PopPushOp, PopPushOp,
PushBranchOp PushBranchOp,
} }
private RestoreType _restoreType; private readonly RestoreType _restoreType;
private ulong _restoreValue; private readonly ulong _restoreValue;
private MergeType _restoreMergeType; private readonly MergeType _restoreMergeType;
public bool ReturningFromVisit => _restoreType != RestoreType.None; public bool ReturningFromVisit => _restoreType != RestoreType.None;
@ -622,9 +621,9 @@ namespace Ryujinx.Graphics.Shader.Decoders
Block target = blocks[pushOp.GetAbsoluteAddress()]; Block target = blocks[pushOp.GetAbsoluteAddress()];
Stack<PathBlockState> workQueue = new Stack<PathBlockState>(); Stack<PathBlockState> workQueue = new();
HashSet<Block> visited = new HashSet<Block>(); HashSet<Block> visited = new();
Stack<(ulong, MergeType)> branchStack = new Stack<(ulong, MergeType)>(); Stack<(ulong, MergeType)> branchStack = new();
void Push(PathBlockState pbs) void Push(PathBlockState pbs)
{ {
@ -759,7 +758,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
{ {
InstName.Pbk => MergeType.Brk, InstName.Pbk => MergeType.Brk,
InstName.Pcnt => MergeType.Cont, InstName.Pcnt => MergeType.Cont,
_ => MergeType.Sync _ => MergeType.Sync,
}; };
} }
@ -769,7 +768,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
{ {
InstName.Brk => MergeType.Brk, InstName.Brk => MergeType.Brk,
InstName.Cont => MergeType.Cont, InstName.Cont => MergeType.Cont,
_ => MergeType.Sync _ => MergeType.Sync,
}; };
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -26,6 +26,6 @@ namespace Ryujinx.Graphics.Shader.Decoders
Tex = 1 << 12, Tex = 1 << 12,
TexB = 1 << 13, TexB = 1 << 13,
Bra = 1 << 14, Bra = 1 << 14,
NoPred = 1 << 15 NoPred = 1 << 15,
} }
} }

View file

@ -24,13 +24,14 @@ namespace Ryujinx.Graphics.Shader.Decoders
} }
} }
private static TableEntry[] _opCodes; private static readonly TableEntry[] _opCodes;
static InstTable() static InstTable()
{ {
_opCodes = new TableEntry[1 << EncodingBits]; _opCodes = new TableEntry[1 << EncodingBits];
#region Instructions #region Instructions
#pragma warning disable IDE0055 // Disable formatting
Add("1110111110100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Al2p, InstEmit.Al2p, InstProps.Rd | InstProps.Ra); Add("1110111110100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Al2p, InstEmit.Al2p, InstProps.Rd | InstProps.Ra);
Add("1110111111011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ald, InstEmit.Ald, InstProps.Rd | InstProps.Ra); Add("1110111111011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ald, InstEmit.Ald, InstProps.Rd | InstProps.Ra);
Add("1110111111110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ast, InstEmit.Ast, InstProps.Ra | InstProps.Rb2 | InstProps.Rc); Add("1110111111110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ast, InstEmit.Ast, InstProps.Ra | InstProps.Rb2 | InstProps.Rc);
@ -325,6 +326,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
Add("0011011x00xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Xmad, InstEmit.XmadI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Rc); Add("0011011x00xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Xmad, InstEmit.XmadI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Rc);
Add("0100111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Xmad, InstEmit.XmadC, InstProps.Rd | InstProps.Ra | InstProps.Rc); Add("0100111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Xmad, InstEmit.XmadC, InstProps.Rd | InstProps.Ra | InstProps.Rc);
Add("010100010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Xmad, InstEmit.XmadRc, InstProps.Rd | InstProps.Ra | InstProps.Rc); Add("010100010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Xmad, InstEmit.XmadRc, InstProps.Rd | InstProps.Ra | InstProps.Rc);
#pragma warning restore IDE0055
#endregion #endregion
} }
@ -357,7 +359,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
xMask = ~xMask; xMask = ~xMask;
TableEntry entry = new TableEntry(name, emitter, props, xBits); TableEntry entry = new(name, emitter, props, xBits);
for (int index = 0; index < (1 << xBits); index++) for (int index = 0; index < (1 << xBits); index++)
{ {

View file

@ -6,7 +6,7 @@ namespace Ryujinx.Graphics.Shader
Lines, Lines,
LinesAdjacency, LinesAdjacency,
Triangles, Triangles,
TrianglesAdjacency TrianglesAdjacency,
} }
static class InputTopologyExtensions static class InputTopologyExtensions
@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.Shader
InputTopology.LinesAdjacency => "lines_adjacency", InputTopology.LinesAdjacency => "lines_adjacency",
InputTopology.Triangles => "triangles", InputTopology.Triangles => "triangles",
InputTopology.TrianglesAdjacency => "triangles_adjacency", InputTopology.TrianglesAdjacency => "triangles_adjacency",
_ => "points" _ => "points",
}; };
} }
@ -33,7 +33,7 @@ namespace Ryujinx.Graphics.Shader
InputTopology.LinesAdjacency => 2, InputTopology.LinesAdjacency => 2,
InputTopology.Triangles or InputTopology.Triangles or
InputTopology.TrianglesAdjacency => 3, InputTopology.TrianglesAdjacency => 3,
_ => 1 _ => 1,
}; };
} }
} }

View file

@ -1,7 +1,6 @@
using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using System.Collections.Generic; using System.Collections.Generic;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
namespace Ryujinx.Graphics.Shader.Instructions namespace Ryujinx.Graphics.Shader.Instructions
@ -21,10 +20,10 @@ namespace Ryujinx.Graphics.Shader.Instructions
Tessellation = TessellationControl | TessellationEvaluation, Tessellation = TessellationControl | TessellationEvaluation,
VertexTessellationGeometry = Vertex | Tessellation | Geometry, VertexTessellationGeometry = Vertex | Tessellation | Geometry,
TessellationGeometryFragment = Tessellation | Geometry | Fragment, TessellationGeometryFragment = Tessellation | Geometry | Fragment,
AllGraphics = Vertex | Tessellation | Geometry | Fragment AllGraphics = Vertex | Tessellation | Geometry | Fragment,
} }
private struct AttributeEntry private readonly struct AttributeEntry
{ {
public int BaseOffset { get; } public int BaseOffset { get; }
public AggregateType Type { get; } public AggregateType Type { get; }
@ -344,7 +343,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
AggregateType.Vector2 => 2, AggregateType.Vector2 => 2,
AggregateType.Vector3 => 3, AggregateType.Vector3 => 3,
AggregateType.Vector4 => 4, AggregateType.Vector4 => 4,
_ => 1 _ => 1,
}; };
} }
} }

View file

@ -7,350 +7,350 @@ namespace Ryujinx.Graphics.Shader.Instructions
{ {
public static void AtomCas(EmitterContext context) public static void AtomCas(EmitterContext context)
{ {
InstAtomCas op = context.GetOp<InstAtomCas>(); context.GetOp<InstAtomCas>();
context.Config.GpuAccessor.Log("Shader instruction AtomCas is not implemented."); context.Config.GpuAccessor.Log("Shader instruction AtomCas is not implemented.");
} }
public static void AtomsCas(EmitterContext context) public static void AtomsCas(EmitterContext context)
{ {
InstAtomsCas op = context.GetOp<InstAtomsCas>(); context.GetOp<InstAtomsCas>();
context.Config.GpuAccessor.Log("Shader instruction AtomsCas is not implemented."); context.Config.GpuAccessor.Log("Shader instruction AtomsCas is not implemented.");
} }
public static void B2r(EmitterContext context) public static void B2r(EmitterContext context)
{ {
InstB2r op = context.GetOp<InstB2r>(); context.GetOp<InstB2r>();
context.Config.GpuAccessor.Log("Shader instruction B2r is not implemented."); context.Config.GpuAccessor.Log("Shader instruction B2r is not implemented.");
} }
public static void Bpt(EmitterContext context) public static void Bpt(EmitterContext context)
{ {
InstBpt op = context.GetOp<InstBpt>(); context.GetOp<InstBpt>();
context.Config.GpuAccessor.Log("Shader instruction Bpt is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Bpt is not implemented.");
} }
public static void Cctl(EmitterContext context) public static void Cctl(EmitterContext context)
{ {
InstCctl op = context.GetOp<InstCctl>(); context.GetOp<InstCctl>();
context.Config.GpuAccessor.Log("Shader instruction Cctl is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Cctl is not implemented.");
} }
public static void Cctll(EmitterContext context) public static void Cctll(EmitterContext context)
{ {
InstCctll op = context.GetOp<InstCctll>(); context.GetOp<InstCctll>();
context.Config.GpuAccessor.Log("Shader instruction Cctll is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Cctll is not implemented.");
} }
public static void Cctlt(EmitterContext context) public static void Cctlt(EmitterContext context)
{ {
InstCctlt op = context.GetOp<InstCctlt>(); context.GetOp<InstCctlt>();
context.Config.GpuAccessor.Log("Shader instruction Cctlt is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Cctlt is not implemented.");
} }
public static void Cs2r(EmitterContext context) public static void Cs2r(EmitterContext context)
{ {
InstCs2r op = context.GetOp<InstCs2r>(); context.GetOp<InstCs2r>();
context.Config.GpuAccessor.Log("Shader instruction Cs2r is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Cs2r is not implemented.");
} }
public static void FchkR(EmitterContext context) public static void FchkR(EmitterContext context)
{ {
InstFchkR op = context.GetOp<InstFchkR>(); context.GetOp<InstFchkR>();
context.Config.GpuAccessor.Log("Shader instruction FchkR is not implemented."); context.Config.GpuAccessor.Log("Shader instruction FchkR is not implemented.");
} }
public static void FchkI(EmitterContext context) public static void FchkI(EmitterContext context)
{ {
InstFchkI op = context.GetOp<InstFchkI>(); context.GetOp<InstFchkI>();
context.Config.GpuAccessor.Log("Shader instruction FchkI is not implemented."); context.Config.GpuAccessor.Log("Shader instruction FchkI is not implemented.");
} }
public static void FchkC(EmitterContext context) public static void FchkC(EmitterContext context)
{ {
InstFchkC op = context.GetOp<InstFchkC>(); context.GetOp<InstFchkC>();
context.Config.GpuAccessor.Log("Shader instruction FchkC is not implemented."); context.Config.GpuAccessor.Log("Shader instruction FchkC is not implemented.");
} }
public static void Getcrsptr(EmitterContext context) public static void Getcrsptr(EmitterContext context)
{ {
InstGetcrsptr op = context.GetOp<InstGetcrsptr>(); context.GetOp<InstGetcrsptr>();
context.Config.GpuAccessor.Log("Shader instruction Getcrsptr is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Getcrsptr is not implemented.");
} }
public static void Getlmembase(EmitterContext context) public static void Getlmembase(EmitterContext context)
{ {
InstGetlmembase op = context.GetOp<InstGetlmembase>(); context.GetOp<InstGetlmembase>();
context.Config.GpuAccessor.Log("Shader instruction Getlmembase is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Getlmembase is not implemented.");
} }
public static void Ide(EmitterContext context) public static void Ide(EmitterContext context)
{ {
InstIde op = context.GetOp<InstIde>(); context.GetOp<InstIde>();
context.Config.GpuAccessor.Log("Shader instruction Ide is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Ide is not implemented.");
} }
public static void IdpR(EmitterContext context) public static void IdpR(EmitterContext context)
{ {
InstIdpR op = context.GetOp<InstIdpR>(); context.GetOp<InstIdpR>();
context.Config.GpuAccessor.Log("Shader instruction IdpR is not implemented."); context.Config.GpuAccessor.Log("Shader instruction IdpR is not implemented.");
} }
public static void IdpC(EmitterContext context) public static void IdpC(EmitterContext context)
{ {
InstIdpC op = context.GetOp<InstIdpC>(); context.GetOp<InstIdpC>();
context.Config.GpuAccessor.Log("Shader instruction IdpC is not implemented."); context.Config.GpuAccessor.Log("Shader instruction IdpC is not implemented.");
} }
public static void ImadspR(EmitterContext context) public static void ImadspR(EmitterContext context)
{ {
InstImadspR op = context.GetOp<InstImadspR>(); context.GetOp<InstImadspR>();
context.Config.GpuAccessor.Log("Shader instruction ImadspR is not implemented."); context.Config.GpuAccessor.Log("Shader instruction ImadspR is not implemented.");
} }
public static void ImadspI(EmitterContext context) public static void ImadspI(EmitterContext context)
{ {
InstImadspI op = context.GetOp<InstImadspI>(); context.GetOp<InstImadspI>();
context.Config.GpuAccessor.Log("Shader instruction ImadspI is not implemented."); context.Config.GpuAccessor.Log("Shader instruction ImadspI is not implemented.");
} }
public static void ImadspC(EmitterContext context) public static void ImadspC(EmitterContext context)
{ {
InstImadspC op = context.GetOp<InstImadspC>(); context.GetOp<InstImadspC>();
context.Config.GpuAccessor.Log("Shader instruction ImadspC is not implemented."); context.Config.GpuAccessor.Log("Shader instruction ImadspC is not implemented.");
} }
public static void ImadspRc(EmitterContext context) public static void ImadspRc(EmitterContext context)
{ {
InstImadspRc op = context.GetOp<InstImadspRc>(); context.GetOp<InstImadspRc>();
context.Config.GpuAccessor.Log("Shader instruction ImadspRc is not implemented."); context.Config.GpuAccessor.Log("Shader instruction ImadspRc is not implemented.");
} }
public static void Jcal(EmitterContext context) public static void Jcal(EmitterContext context)
{ {
InstJcal op = context.GetOp<InstJcal>(); context.GetOp<InstJcal>();
context.Config.GpuAccessor.Log("Shader instruction Jcal is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Jcal is not implemented.");
} }
public static void Jmp(EmitterContext context) public static void Jmp(EmitterContext context)
{ {
InstJmp op = context.GetOp<InstJmp>(); context.GetOp<InstJmp>();
context.Config.GpuAccessor.Log("Shader instruction Jmp is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Jmp is not implemented.");
} }
public static void Jmx(EmitterContext context) public static void Jmx(EmitterContext context)
{ {
InstJmx op = context.GetOp<InstJmx>(); context.GetOp<InstJmx>();
context.Config.GpuAccessor.Log("Shader instruction Jmx is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Jmx is not implemented.");
} }
public static void Ld(EmitterContext context) public static void Ld(EmitterContext context)
{ {
InstLd op = context.GetOp<InstLd>(); context.GetOp<InstLd>();
context.Config.GpuAccessor.Log("Shader instruction Ld is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Ld is not implemented.");
} }
public static void Lepc(EmitterContext context) public static void Lepc(EmitterContext context)
{ {
InstLepc op = context.GetOp<InstLepc>(); context.GetOp<InstLepc>();
context.Config.GpuAccessor.Log("Shader instruction Lepc is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Lepc is not implemented.");
} }
public static void Longjmp(EmitterContext context) public static void Longjmp(EmitterContext context)
{ {
InstLongjmp op = context.GetOp<InstLongjmp>(); context.GetOp<InstLongjmp>();
context.Config.GpuAccessor.Log("Shader instruction Longjmp is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Longjmp is not implemented.");
} }
public static void Pexit(EmitterContext context) public static void Pexit(EmitterContext context)
{ {
InstPexit op = context.GetOp<InstPexit>(); context.GetOp<InstPexit>();
context.Config.GpuAccessor.Log("Shader instruction Pexit is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Pexit is not implemented.");
} }
public static void Pixld(EmitterContext context) public static void Pixld(EmitterContext context)
{ {
InstPixld op = context.GetOp<InstPixld>(); context.GetOp<InstPixld>();
context.Config.GpuAccessor.Log("Shader instruction Pixld is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Pixld is not implemented.");
} }
public static void Plongjmp(EmitterContext context) public static void Plongjmp(EmitterContext context)
{ {
InstPlongjmp op = context.GetOp<InstPlongjmp>(); context.GetOp<InstPlongjmp>();
context.Config.GpuAccessor.Log("Shader instruction Plongjmp is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Plongjmp is not implemented.");
} }
public static void Pret(EmitterContext context) public static void Pret(EmitterContext context)
{ {
InstPret op = context.GetOp<InstPret>(); context.GetOp<InstPret>();
context.Config.GpuAccessor.Log("Shader instruction Pret is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Pret is not implemented.");
} }
public static void PrmtR(EmitterContext context) public static void PrmtR(EmitterContext context)
{ {
InstPrmtR op = context.GetOp<InstPrmtR>(); context.GetOp<InstPrmtR>();
context.Config.GpuAccessor.Log("Shader instruction PrmtR is not implemented."); context.Config.GpuAccessor.Log("Shader instruction PrmtR is not implemented.");
} }
public static void PrmtI(EmitterContext context) public static void PrmtI(EmitterContext context)
{ {
InstPrmtI op = context.GetOp<InstPrmtI>(); context.GetOp<InstPrmtI>();
context.Config.GpuAccessor.Log("Shader instruction PrmtI is not implemented."); context.Config.GpuAccessor.Log("Shader instruction PrmtI is not implemented.");
} }
public static void PrmtC(EmitterContext context) public static void PrmtC(EmitterContext context)
{ {
InstPrmtC op = context.GetOp<InstPrmtC>(); context.GetOp<InstPrmtC>();
context.Config.GpuAccessor.Log("Shader instruction PrmtC is not implemented."); context.Config.GpuAccessor.Log("Shader instruction PrmtC is not implemented.");
} }
public static void PrmtRc(EmitterContext context) public static void PrmtRc(EmitterContext context)
{ {
InstPrmtRc op = context.GetOp<InstPrmtRc>(); context.GetOp<InstPrmtRc>();
context.Config.GpuAccessor.Log("Shader instruction PrmtRc is not implemented."); context.Config.GpuAccessor.Log("Shader instruction PrmtRc is not implemented.");
} }
public static void R2b(EmitterContext context) public static void R2b(EmitterContext context)
{ {
InstR2b op = context.GetOp<InstR2b>(); context.GetOp<InstR2b>();
context.Config.GpuAccessor.Log("Shader instruction R2b is not implemented."); context.Config.GpuAccessor.Log("Shader instruction R2b is not implemented.");
} }
public static void Ram(EmitterContext context) public static void Ram(EmitterContext context)
{ {
InstRam op = context.GetOp<InstRam>(); context.GetOp<InstRam>();
context.Config.GpuAccessor.Log("Shader instruction Ram is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Ram is not implemented.");
} }
public static void Rtt(EmitterContext context) public static void Rtt(EmitterContext context)
{ {
InstRtt op = context.GetOp<InstRtt>(); context.GetOp<InstRtt>();
context.Config.GpuAccessor.Log("Shader instruction Rtt is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Rtt is not implemented.");
} }
public static void Sam(EmitterContext context) public static void Sam(EmitterContext context)
{ {
InstSam op = context.GetOp<InstSam>(); context.GetOp<InstSam>();
context.Config.GpuAccessor.Log("Shader instruction Sam is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Sam is not implemented.");
} }
public static void Setcrsptr(EmitterContext context) public static void Setcrsptr(EmitterContext context)
{ {
InstSetcrsptr op = context.GetOp<InstSetcrsptr>(); context.GetOp<InstSetcrsptr>();
context.Config.GpuAccessor.Log("Shader instruction Setcrsptr is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Setcrsptr is not implemented.");
} }
public static void Setlmembase(EmitterContext context) public static void Setlmembase(EmitterContext context)
{ {
InstSetlmembase op = context.GetOp<InstSetlmembase>(); context.GetOp<InstSetlmembase>();
context.Config.GpuAccessor.Log("Shader instruction Setlmembase is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Setlmembase is not implemented.");
} }
public static void St(EmitterContext context) public static void St(EmitterContext context)
{ {
InstSt op = context.GetOp<InstSt>(); context.GetOp<InstSt>();
context.Config.GpuAccessor.Log("Shader instruction St is not implemented."); context.Config.GpuAccessor.Log("Shader instruction St is not implemented.");
} }
public static void Stp(EmitterContext context) public static void Stp(EmitterContext context)
{ {
InstStp op = context.GetOp<InstStp>(); context.GetOp<InstStp>();
context.Config.GpuAccessor.Log("Shader instruction Stp is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Stp is not implemented.");
} }
public static void Txa(EmitterContext context) public static void Txa(EmitterContext context)
{ {
InstTxa op = context.GetOp<InstTxa>(); context.GetOp<InstTxa>();
context.Config.GpuAccessor.Log("Shader instruction Txa is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Txa is not implemented.");
} }
public static void Vabsdiff(EmitterContext context) public static void Vabsdiff(EmitterContext context)
{ {
InstVabsdiff op = context.GetOp<InstVabsdiff>(); context.GetOp<InstVabsdiff>();
context.Config.GpuAccessor.Log("Shader instruction Vabsdiff is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Vabsdiff is not implemented.");
} }
public static void Vabsdiff4(EmitterContext context) public static void Vabsdiff4(EmitterContext context)
{ {
InstVabsdiff4 op = context.GetOp<InstVabsdiff4>(); context.GetOp<InstVabsdiff4>();
context.Config.GpuAccessor.Log("Shader instruction Vabsdiff4 is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Vabsdiff4 is not implemented.");
} }
public static void Vadd(EmitterContext context) public static void Vadd(EmitterContext context)
{ {
InstVadd op = context.GetOp<InstVadd>(); context.GetOp<InstVadd>();
context.Config.GpuAccessor.Log("Shader instruction Vadd is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Vadd is not implemented.");
} }
public static void Votevtg(EmitterContext context) public static void Votevtg(EmitterContext context)
{ {
InstVotevtg op = context.GetOp<InstVotevtg>(); context.GetOp<InstVotevtg>();
context.Config.GpuAccessor.Log("Shader instruction Votevtg is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Votevtg is not implemented.");
} }
public static void Vset(EmitterContext context) public static void Vset(EmitterContext context)
{ {
InstVset op = context.GetOp<InstVset>(); context.GetOp<InstVset>();
context.Config.GpuAccessor.Log("Shader instruction Vset is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Vset is not implemented.");
} }
public static void Vshl(EmitterContext context) public static void Vshl(EmitterContext context)
{ {
InstVshl op = context.GetOp<InstVshl>(); context.GetOp<InstVshl>();
context.Config.GpuAccessor.Log("Shader instruction Vshl is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Vshl is not implemented.");
} }
public static void Vshr(EmitterContext context) public static void Vshr(EmitterContext context)
{ {
InstVshr op = context.GetOp<InstVshr>(); context.GetOp<InstVshr>();
context.Config.GpuAccessor.Log("Shader instruction Vshr is not implemented."); context.Config.GpuAccessor.Log("Shader instruction Vshr is not implemented.");
} }

View file

@ -2,7 +2,6 @@ using Ryujinx.Graphics.Shader.Decoders;
using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using System; using System;
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
@ -18,7 +17,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
IDstFmt.S16 => short.MinValue, IDstFmt.S16 => short.MinValue,
IDstFmt.U32 => uint.MinValue, IDstFmt.U32 => uint.MinValue,
IDstFmt.S32 => int.MinValue, IDstFmt.S32 => int.MinValue,
_ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type.") _ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type."),
}; };
} }
@ -30,7 +29,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
IDstFmt.S16 => short.MaxValue, IDstFmt.S16 => short.MaxValue,
IDstFmt.U32 => uint.MaxValue, IDstFmt.U32 => uint.MaxValue,
IDstFmt.S32 => int.MaxValue, IDstFmt.S32 => int.MaxValue,
_ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type.") _ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type."),
}; };
} }
@ -44,7 +43,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
ISrcDstFmt.S16 => short.MinValue, ISrcDstFmt.S16 => short.MinValue,
ISrcDstFmt.U32 => uint.MinValue, ISrcDstFmt.U32 => uint.MinValue,
ISrcDstFmt.S32 => int.MinValue, ISrcDstFmt.S32 => int.MinValue,
_ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type.") _ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type."),
}; };
} }
@ -58,7 +57,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
ISrcDstFmt.S16 => short.MaxValue, ISrcDstFmt.S16 => short.MaxValue,
ISrcDstFmt.U32 => uint.MaxValue, ISrcDstFmt.U32 => uint.MaxValue,
ISrcDstFmt.S32 => int.MaxValue, ISrcDstFmt.S32 => int.MaxValue,
_ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type.") _ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type."),
}; };
} }
@ -69,7 +68,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
BoolOp.And => context.BitwiseAnd(input, pred), BoolOp.And => context.BitwiseAnd(input, pred),
BoolOp.Or => context.BitwiseOr(input, pred), BoolOp.Or => context.BitwiseOr(input, pred),
BoolOp.Xor => context.BitwiseExclusiveOr(input, pred), BoolOp.Xor => context.BitwiseExclusiveOr(input, pred),
_ => input _ => input,
}; };
} }
@ -89,7 +88,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
VectorSelect.S8B3 => SignExtendTo32(context, context.ShiftRightU32(src, Const(24)), 8), VectorSelect.S8B3 => SignExtendTo32(context, context.ShiftRightU32(src, Const(24)), 8),
VectorSelect.S16H0 => SignExtendTo32(context, context.ShiftRightU32(src, Const(0)), 16), VectorSelect.S16H0 => SignExtendTo32(context, context.ShiftRightU32(src, Const(0)), 16),
VectorSelect.S16H1 => SignExtendTo32(context, context.ShiftRightU32(src, Const(16)), 16), VectorSelect.S16H1 => SignExtendTo32(context, context.ShiftRightU32(src, Const(16)), 16),
_ => src _ => src,
}; };
} }

View file

@ -33,7 +33,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
for (int index = 0; index < (int)op.AlSize + 1; index++) for (int index = 0; index < (int)op.AlSize + 1; index++)
{ {
Register rd = new Register(op.Dest + index, RegisterType.Gpr); Register rd = new(op.Dest + index, RegisterType.Gpr);
if (rd.IsRZ) if (rd.IsRZ)
{ {
@ -91,7 +91,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
break; break;
} }
Register rd = new Register(op.SrcB + index, RegisterType.Gpr); Register rd = new(op.SrcB + index, RegisterType.Gpr);
if (op.Phys) if (op.Phys)
{ {

View file

@ -22,7 +22,9 @@ namespace Ryujinx.Graphics.Shader.Instructions
public static void Depbar(EmitterContext context) public static void Depbar(EmitterContext context)
{ {
#pragma warning disable IDE0059 // Remove unnecessary value assignment
InstDepbar op = context.GetOp<InstDepbar>(); InstDepbar op = context.GetOp<InstDepbar>();
#pragma warning restore IDE0059
// No operation. // No operation.
} }

View file

@ -1,7 +1,6 @@
using Ryujinx.Graphics.Shader.Decoders; using Ryujinx.Graphics.Shader.Decoders;
using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper;
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
@ -80,7 +79,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
Ccc.Oft => GetVF(), Ccc.Oft => GetVF(),
Ccc.Rle => context.BitwiseOr(GetNF(), GetZF()), Ccc.Rle => context.BitwiseOr(GetNF(), GetZF()),
Ccc.Rgt => context.BitwiseNot(context.BitwiseOr(GetNF(), GetZF())), Ccc.Rgt => context.BitwiseNot(context.BitwiseOr(GetNF(), GetZF())),
_ => Const(defaultCond) _ => Const(defaultCond),
}; };
} }
} }

View file

@ -2,7 +2,6 @@ using Ryujinx.Graphics.Shader.Decoders;
using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using System; using System;
using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper;
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
@ -140,7 +139,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
IntegerRound.Floor => context.FPFloor(srcB, srcType.ToInstFPType()), IntegerRound.Floor => context.FPFloor(srcB, srcType.ToInstFPType()),
IntegerRound.Ceil => context.FPCeiling(srcB, srcType.ToInstFPType()), IntegerRound.Ceil => context.FPCeiling(srcB, srcType.ToInstFPType()),
IntegerRound.Trunc => context.FPTruncate(srcB, srcType.ToInstFPType()), IntegerRound.Trunc => context.FPTruncate(srcB, srcType.ToInstFPType()),
_ => srcB _ => srcB,
}; };
} }
@ -191,7 +190,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
RoundMode2.Floor => context.FPFloor(srcB, fpType), RoundMode2.Floor => context.FPFloor(srcB, fpType),
RoundMode2.Ceil => context.FPCeiling(srcB, fpType), RoundMode2.Ceil => context.FPCeiling(srcB, fpType),
RoundMode2.Trunc => context.FPTruncate(srcB, fpType), RoundMode2.Trunc => context.FPTruncate(srcB, fpType),
_ => srcB _ => srcB,
}; };
if (!isSignedInt) if (!isSignedInt)

View file

@ -1,7 +1,6 @@
using Ryujinx.Graphics.Shader.Decoders; using Ryujinx.Graphics.Shader.Decoders;
using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper;
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
@ -458,7 +457,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
MultiplyScale.M2 => ConstF(2f), MultiplyScale.M2 => ConstF(2f),
MultiplyScale.M4 => ConstF(4f), MultiplyScale.M4 => ConstF(4f),
MultiplyScale.M8 => ConstF(8f), MultiplyScale.M8 => ConstF(8f),
_ => ConstF(1f) // Invalid, behave as if it had no scale. _ => ConstF(1f), // Invalid, behave as if it had no scale.
}; };
if (scaleConst.AsFloat() == 1f) if (scaleConst.AsFloat() == 1f)

View file

@ -2,7 +2,6 @@ using Ryujinx.Graphics.Shader.Decoders;
using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using System; using System;
using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper;
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
@ -546,20 +545,16 @@ namespace Ryujinx.Graphics.Shader.Instructions
} }
else else
{ {
Instruction inst; var inst = (cond & ~FComp.Nan) switch
switch (cond & ~FComp.Nan)
{ {
case FComp.Lt: inst = Instruction.CompareLess; break; FComp.Lt => Instruction.CompareLess,
case FComp.Eq: inst = Instruction.CompareEqual; break; FComp.Eq => Instruction.CompareEqual,
case FComp.Le: inst = Instruction.CompareLessOrEqual; break; FComp.Le => Instruction.CompareLessOrEqual,
case FComp.Gt: inst = Instruction.CompareGreater; break; FComp.Gt => Instruction.CompareGreater,
case FComp.Ne: inst = Instruction.CompareNotEqual; break; FComp.Ne => Instruction.CompareNotEqual,
case FComp.Ge: inst = Instruction.CompareGreaterOrEqual; break; FComp.Ge => Instruction.CompareGreaterOrEqual,
_ => throw new ArgumentException($"Unexpected condition \"{cond}\"."),
default: throw new ArgumentException($"Unexpected condition \"{cond}\"."); };
}
res = context.Add(inst | fpType, Local(), srcA, srcB); res = context.Add(inst | fpType, Local(), srcA, srcB);
if ((cond & FComp.Nan) != 0) if ((cond & FComp.Nan) != 0)

View file

@ -3,8 +3,6 @@ using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
namespace Ryujinx.Graphics.Shader.Instructions namespace Ryujinx.Graphics.Shader.Instructions
@ -13,14 +11,14 @@ namespace Ryujinx.Graphics.Shader.Instructions
{ {
public static void Bra(EmitterContext context) public static void Bra(EmitterContext context)
{ {
InstBra op = context.GetOp<InstBra>(); context.GetOp<InstBra>();
EmitBranch(context, context.CurrBlock.Successors[^1].Address); EmitBranch(context, context.CurrBlock.Successors[^1].Address);
} }
public static void Brk(EmitterContext context) public static void Brk(EmitterContext context)
{ {
InstBrk op = context.GetOp<InstBrk>(); context.GetOp<InstBrk>();
EmitBrkContSync(context); EmitBrkContSync(context);
} }
@ -123,7 +121,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
public static void Cal(EmitterContext context) public static void Cal(EmitterContext context)
{ {
InstCal op = context.GetOp<InstCal>(); context.GetOp<InstCal>();
DecodedFunction function = context.Program.GetFunctionByAddress(context.CurrOp.GetAbsoluteAddress()); DecodedFunction function = context.Program.GetFunctionByAddress(context.CurrOp.GetAbsoluteAddress());
@ -147,7 +145,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
public static void Cont(EmitterContext context) public static void Cont(EmitterContext context)
{ {
InstCont op = context.GetOp<InstCont>(); context.GetOp<InstCont>();
EmitBrkContSync(context); EmitBrkContSync(context);
} }
@ -185,28 +183,28 @@ namespace Ryujinx.Graphics.Shader.Instructions
public static void Kil(EmitterContext context) public static void Kil(EmitterContext context)
{ {
InstKil op = context.GetOp<InstKil>(); context.GetOp<InstKil>();
context.Discard(); context.Discard();
} }
public static void Pbk(EmitterContext context) public static void Pbk(EmitterContext context)
{ {
InstPbk op = context.GetOp<InstPbk>(); context.GetOp<InstPbk>();
EmitPbkPcntSsy(context); EmitPbkPcntSsy(context);
} }
public static void Pcnt(EmitterContext context) public static void Pcnt(EmitterContext context)
{ {
InstPcnt op = context.GetOp<InstPcnt>(); context.GetOp<InstPcnt>();
EmitPbkPcntSsy(context); EmitPbkPcntSsy(context);
} }
public static void Ret(EmitterContext context) public static void Ret(EmitterContext context)
{ {
InstRet op = context.GetOp<InstRet>(); context.GetOp<InstRet>();
if (context.IsNonMain) if (context.IsNonMain)
{ {
@ -220,14 +218,14 @@ namespace Ryujinx.Graphics.Shader.Instructions
public static void Ssy(EmitterContext context) public static void Ssy(EmitterContext context)
{ {
InstSsy op = context.GetOp<InstSsy>(); context.GetOp<InstSsy>();
EmitPbkPcntSsy(context); EmitPbkPcntSsy(context);
} }
public static void Sync(EmitterContext context) public static void Sync(EmitterContext context)
{ {
InstSync op = context.GetOp<InstSync>(); context.GetOp<InstSync>();
EmitBrkContSync(context); EmitBrkContSync(context);
} }
@ -275,7 +273,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
private static void EmitBranch(EmitterContext context, ulong address) private static void EmitBranch(EmitterContext context, ulong address)
{ {
InstOp op = context.CurrOp; InstOp op = context.CurrOp;
InstConditional opCond = new InstConditional(op.RawOpCode); InstConditional opCond = new(op.RawOpCode);
// If we're branching to the next instruction, then the branch // If we're branching to the next instruction, then the branch
// is useless and we can ignore it. // is useless and we can ignore it.

View file

@ -3,7 +3,6 @@ using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using System; using System;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
namespace Ryujinx.Graphics.Shader.Instructions namespace Ryujinx.Graphics.Shader.Instructions
@ -111,7 +110,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
return new Operand[] return new Operand[]
{ {
ConstF((float)Unsafe.As<ushort, Half>(ref low)), ConstF((float)Unsafe.As<ushort, Half>(ref low)),
ConstF((float)Unsafe.As<ushort, Half>(ref high)) ConstF((float)Unsafe.As<ushort, Half>(ref high)),
}; };
} }
@ -123,7 +122,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
return new Operand[] return new Operand[]
{ {
ConstF((float)Unsafe.As<ushort, Half>(ref low)), ConstF((float)Unsafe.As<ushort, Half>(ref low)),
ConstF((float)Unsafe.As<ushort, Half>(ref high)) ConstF((float)Unsafe.As<ushort, Half>(ref high)),
}; };
} }
@ -139,42 +138,37 @@ namespace Ryujinx.Graphics.Shader.Instructions
public static Operand[] GetHalfUnpacked(EmitterContext context, Operand src, HalfSwizzle swizzle) public static Operand[] GetHalfUnpacked(EmitterContext context, Operand src, HalfSwizzle swizzle)
{ {
switch (swizzle) return swizzle switch
{ {
case HalfSwizzle.F16: HalfSwizzle.F16 => new Operand[]
return new Operand[]
{ {
context.UnpackHalf2x16Low (src), context.UnpackHalf2x16Low (src),
context.UnpackHalf2x16High(src) context.UnpackHalf2x16High(src),
}; },
HalfSwizzle.F32 => new Operand[] { src, src },
case HalfSwizzle.F32: return new Operand[] { src, src }; HalfSwizzle.H0H0 => new Operand[]
case HalfSwizzle.H0H0:
return new Operand[]
{ {
context.UnpackHalf2x16Low(src), context.UnpackHalf2x16Low(src),
context.UnpackHalf2x16Low(src) context.UnpackHalf2x16Low(src),
}; },
HalfSwizzle.H1H1 => new Operand[]
case HalfSwizzle.H1H1:
return new Operand[]
{ {
context.UnpackHalf2x16High(src), context.UnpackHalf2x16High(src),
context.UnpackHalf2x16High(src) context.UnpackHalf2x16High(src),
},
_ => throw new ArgumentException($"Invalid swizzle \"{swizzle}\"."),
}; };
} }
throw new ArgumentException($"Invalid swizzle \"{swizzle}\".");
}
public static Operand GetHalfPacked(EmitterContext context, OFmt swizzle, Operand[] results, int rd) public static Operand GetHalfPacked(EmitterContext context, OFmt swizzle, Operand[] results, int rd)
{ {
switch (swizzle) switch (swizzle)
{ {
case OFmt.F16: return context.PackHalf2x16(results[0], results[1]); case OFmt.F16:
return context.PackHalf2x16(results[0], results[1]);
case OFmt.F32: return results[0]; case OFmt.F32:
return results[0];
case OFmt.MrgH0: case OFmt.MrgH0:
{ {

View file

@ -510,7 +510,9 @@ namespace Ryujinx.Graphics.Shader.Instructions
aLow = context.BitwiseNot(aLow); aLow = context.BitwiseNot(aLow);
aHigh = context.BitwiseNot(aHigh); aHigh = context.BitwiseNot(aHigh);
#pragma warning disable IDE0059 // Remove unnecessary value assignment
aLow = AddWithCarry(context, aLow, Const(1), out Operand aLowCOut); aLow = AddWithCarry(context, aLow, Const(1), out Operand aLowCOut);
#pragma warning restore IDE0059
aHigh = context.IAdd(aHigh, aLowCOut); aHigh = context.IAdd(aHigh, aLowCOut);
} }

View file

@ -2,7 +2,6 @@ using Ryujinx.Graphics.Shader.Decoders;
using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using System; using System;
using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper;
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
@ -220,7 +219,9 @@ namespace Ryujinx.Graphics.Shader.Instructions
else else
{ {
res = context.ISubtract(srcA, srcB); res = context.ISubtract(srcA, srcB);
#pragma warning disable IDE0059 // Remove unnecessary value assignment
res = context.IAdd(res, context.BitwiseNot(GetCF())); res = context.IAdd(res, context.BitwiseNot(GetCF()));
#pragma warning restore IDE0059
switch (cond) switch (cond)
{ {
@ -287,17 +288,25 @@ namespace Ryujinx.Graphics.Shader.Instructions
IComp.Gt => Instruction.CompareGreaterU32, IComp.Gt => Instruction.CompareGreaterU32,
IComp.Ne => Instruction.CompareNotEqual, IComp.Ne => Instruction.CompareNotEqual,
IComp.Ge => Instruction.CompareGreaterOrEqualU32, IComp.Ge => Instruction.CompareGreaterOrEqualU32,
_ => throw new InvalidOperationException($"Unexpected condition \"{cond}\".") _ => throw new InvalidOperationException($"Unexpected condition \"{cond}\"."),
}; };
if (isSigned) if (isSigned)
{ {
switch (cond) switch (cond)
{ {
case IComp.Lt: inst = Instruction.CompareLess; break; case IComp.Lt:
case IComp.Le: inst = Instruction.CompareLessOrEqual; break; inst = Instruction.CompareLess;
case IComp.Gt: inst = Instruction.CompareGreater; break; break;
case IComp.Ge: inst = Instruction.CompareGreaterOrEqual; break; case IComp.Le:
inst = Instruction.CompareLessOrEqual;
break;
case IComp.Gt:
inst = Instruction.CompareGreater;
break;
case IComp.Ge:
inst = Instruction.CompareGreaterOrEqual;
break;
} }
} }

View file

@ -1,7 +1,6 @@
using Ryujinx.Graphics.Shader.Decoders; using Ryujinx.Graphics.Shader.Decoders;
using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper;
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
@ -103,10 +102,10 @@ namespace Ryujinx.Graphics.Shader.Instructions
Operand res = logicOp switch Operand res = logicOp switch
{ {
LogicOp.And => res = context.BitwiseAnd(srcA, srcB), LogicOp.And => context.BitwiseAnd(srcA, srcB),
LogicOp.Or => res = context.BitwiseOr(srcA, srcB), LogicOp.Or => context.BitwiseOr(srcA, srcB),
LogicOp.Xor => res = context.BitwiseExclusiveOr(srcA, srcB), LogicOp.Xor => context.BitwiseExclusiveOr(srcA, srcB),
_ => srcB _ => srcB,
}; };
EmitLopPredWrite(context, res, predOp, destPred); EmitLopPredWrite(context, res, predOp, destPred);

View file

@ -2,7 +2,6 @@ using Ryujinx.Graphics.Shader.Decoders;
using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using System.Numerics; using System.Numerics;
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
@ -48,7 +47,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
AtomsSize.S32 => AtomSize.S32, AtomsSize.S32 => AtomSize.S32,
AtomsSize.U64 => AtomSize.U64, AtomsSize.U64 => AtomSize.U64,
AtomsSize.S64 => AtomSize.S64, AtomsSize.S64 => AtomSize.S64,
_ => AtomSize.U32 _ => AtomSize.U32,
}; };
Operand id = Const(context.Config.ResourceManager.SharedMemoryId); Operand id = Const(context.Config.ResourceManager.SharedMemoryId);
@ -85,7 +84,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
for (int index = 0; index < count; index++) for (int index = 0; index < count; index++)
{ {
Register dest = new Register(op.Dest + index, RegisterType.Gpr); Register dest = new(op.Dest + index, RegisterType.Gpr);
if (dest.IsRZ) if (dest.IsRZ)
{ {
@ -309,14 +308,14 @@ namespace Ryujinx.Graphics.Shader.Instructions
{ {
LsSize2.B64 => 2, LsSize2.B64 => 2,
LsSize2.B128 => 4, LsSize2.B128 => 4,
_ => 1 _ => 1,
}; };
Operand baseOffset = context.Copy(srcA); Operand baseOffset = context.Copy(srcA);
for (int index = 0; index < count; index++) for (int index = 0; index < count; index++)
{ {
Register dest = new Register(rd + index, RegisterType.Gpr); Register dest = new(rd + index, RegisterType.Gpr);
if (dest.IsRZ) if (dest.IsRZ)
{ {
@ -354,7 +353,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
for (int index = 0; index < count; index++) for (int index = 0; index < count; index++)
{ {
Register dest = new Register(rd + index, RegisterType.Gpr); Register dest = new(rd + index, RegisterType.Gpr);
if (dest.IsRZ) if (dest.IsRZ)
{ {
@ -390,7 +389,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
{ {
LsSize2.B64 => 2, LsSize2.B64 => 2,
LsSize2.B128 => 4, LsSize2.B128 => 4,
_ => 1 _ => 1,
}; };
Operand baseOffset = context.Copy(srcA); Operand baseOffset = context.Copy(srcA);
@ -476,22 +475,18 @@ namespace Ryujinx.Graphics.Shader.Instructions
LsSize.S8 => StorageKind.GlobalMemoryS8, LsSize.S8 => StorageKind.GlobalMemoryS8,
LsSize.U16 => StorageKind.GlobalMemoryU16, LsSize.U16 => StorageKind.GlobalMemoryU16,
LsSize.S16 => StorageKind.GlobalMemoryS16, LsSize.S16 => StorageKind.GlobalMemoryS16,
_ => StorageKind.GlobalMemory _ => StorageKind.GlobalMemory,
}; };
} }
private static int GetVectorCount(LsSize size) private static int GetVectorCount(LsSize size)
{ {
switch (size) return size switch
{ {
case LsSize.B64: LsSize.B64 => 2,
return 2; LsSize.B128 or LsSize.UB128 => 4,
case LsSize.B128: _ => 1,
case LsSize.UB128: };
return 4;
}
return 1;
} }
private static (Operand, Operand) Get40BitsAddress( private static (Operand, Operand) Get40BitsAddress(
@ -544,10 +539,18 @@ namespace Ryujinx.Graphics.Shader.Instructions
switch (size) switch (size)
{ {
case LsSize.U8: value = ZeroExtendTo32(context, value, 8); break; case LsSize.U8:
case LsSize.U16: value = ZeroExtendTo32(context, value, 16); break; value = ZeroExtendTo32(context, value, 8);
case LsSize.S8: value = SignExtendTo32(context, value, 8); break; break;
case LsSize.S16: value = SignExtendTo32(context, value, 16); break; case LsSize.U16:
value = ZeroExtendTo32(context, value, 16);
break;
case LsSize.S8:
value = SignExtendTo32(context, value, 8);
break;
case LsSize.S16:
value = SignExtendTo32(context, value, 16);
break;
} }
return value; return value;

View file

@ -7,7 +7,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
{ {
public static void Nop(EmitterContext context) public static void Nop(EmitterContext context)
{ {
InstNop op = context.GetOp<InstNop>(); context.GetOp<InstNop>();
// No operation. // No operation.
} }

View file

@ -4,7 +4,6 @@ using Ryujinx.Graphics.Shader.Translation;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Numerics; using System.Numerics;
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
@ -221,7 +220,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
Operand destOperand = dest != RegisterConsts.RegisterZeroIndex ? Register(dest, RegisterType.Gpr) : null; Operand destOperand = dest != RegisterConsts.RegisterZeroIndex ? Register(dest, RegisterType.Gpr) : null;
List<Operand> sourcesList = new List<Operand>(); List<Operand> sourcesList = new();
if (isBindless) if (isBindless)
{ {
@ -325,7 +324,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
return context.Copy(Register(srcA++, RegisterType.Gpr)); return context.Copy(Register(srcA++, RegisterType.Gpr));
} }
List<Operand> sourcesList = new List<Operand>(); List<Operand> sourcesList = new();
if (isBindless) if (isBindless)
{ {
@ -445,10 +444,18 @@ namespace Ryujinx.Graphics.Shader.Instructions
switch (size) switch (size)
{ {
case SuSize.U8: context.Copy(dests[0], ZeroExtendTo32(context, dests[0], 8)); break; case SuSize.U8:
case SuSize.U16: context.Copy(dests[0], ZeroExtendTo32(context, dests[0], 16)); break; context.Copy(dests[0], ZeroExtendTo32(context, dests[0], 8));
case SuSize.S8: context.Copy(dests[0], SignExtendTo32(context, dests[0], 8)); break; break;
case SuSize.S16: context.Copy(dests[0], SignExtendTo32(context, dests[0], 16)); break; case SuSize.U16:
context.Copy(dests[0], ZeroExtendTo32(context, dests[0], 16));
break;
case SuSize.S8:
context.Copy(dests[0], SignExtendTo32(context, dests[0], 8));
break;
case SuSize.S16:
context.Copy(dests[0], SignExtendTo32(context, dests[0], 16));
break;
} }
} }
} }
@ -493,7 +500,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
return context.Copy(Register(srcB++, RegisterType.Gpr)); return context.Copy(Register(srcB++, RegisterType.Gpr));
} }
List<Operand> sourcesList = new List<Operand>(); List<Operand> sourcesList = new();
if (isBindless) if (isBindless)
{ {
@ -600,7 +607,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
return context.Copy(Register(srcB++, RegisterType.Gpr)); return context.Copy(Register(srcB++, RegisterType.Gpr));
} }
List<Operand> sourcesList = new List<Operand>(); List<Operand> sourcesList = new();
if (isBindless) if (isBindless)
{ {
@ -699,7 +706,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
SuatomSize.S64 => 3, SuatomSize.S64 => 3,
SuatomSize.Sd32 => 2, SuatomSize.Sd32 => 2,
SuatomSize.Sd64 => 3, SuatomSize.Sd64 => 3,
_ => 2 _ => 2,
}; };
} }
@ -715,7 +722,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
SuatomSize.S64 => TextureFormat.R32G32Uint, SuatomSize.S64 => TextureFormat.R32G32Uint,
SuatomSize.Sd32 => TextureFormat.R32Uint, SuatomSize.Sd32 => TextureFormat.R32Uint,
SuatomSize.Sd64 => TextureFormat.R32G32Uint, SuatomSize.Sd64 => TextureFormat.R32G32Uint,
_ => TextureFormat.R32Uint _ => TextureFormat.R32Uint,
}; };
} }
@ -732,7 +739,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
SuatomOp.Or => TextureFlags.BitwiseOr, SuatomOp.Or => TextureFlags.BitwiseOr,
SuatomOp.Xor => TextureFlags.BitwiseXor, SuatomOp.Xor => TextureFlags.BitwiseXor,
SuatomOp.Exch => TextureFlags.Swap, SuatomOp.Exch => TextureFlags.Swap,
_ => TextureFlags.Add _ => TextureFlags.Add,
}; };
} }
@ -743,7 +750,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
SuSize.B64 => 2, SuSize.B64 => 2,
SuSize.B128 => 4, SuSize.B128 => 4,
SuSize.UB128 => 4, SuSize.UB128 => 4,
_ => 1 _ => 1,
}; };
} }
@ -759,7 +766,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
SuSize.B64 => 3, SuSize.B64 => 3,
SuSize.B128 => 4, SuSize.B128 => 4,
SuSize.UB128 => 4, SuSize.UB128 => 4,
_ => 2 _ => 2,
}; };
} }
@ -775,7 +782,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
SuSize.B64 => TextureFormat.R32G32Uint, SuSize.B64 => TextureFormat.R32G32Uint,
SuSize.B128 => TextureFormat.R32G32B32A32Uint, SuSize.B128 => TextureFormat.R32G32B32A32Uint,
SuSize.UB128 => TextureFormat.R32G32B32A32Uint, SuSize.UB128 => TextureFormat.R32G32B32A32Uint,
_ => TextureFormat.R32Uint _ => TextureFormat.R32Uint,
}; };
} }
@ -789,7 +796,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
SuDim._2d => SamplerType.Texture2D, SuDim._2d => SamplerType.Texture2D,
SuDim._2dArray => SamplerType.Texture2D | SamplerType.Array, SuDim._2dArray => SamplerType.Texture2D | SamplerType.Array,
SuDim._3d => SamplerType.Texture3D, SuDim._3d => SamplerType.Texture3D,
_ => SamplerType.None _ => SamplerType.None,
}; };
} }
} }

View file

@ -4,7 +4,6 @@ using Ryujinx.Graphics.Shader.Translation;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Numerics; using System.Numerics;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
namespace Ryujinx.Graphics.Shader.Instructions namespace Ryujinx.Graphics.Shader.Instructions
@ -14,7 +13,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
private static readonly int[,] _maskLut = new int[,] private static readonly int[,] _maskLut = new int[,]
{ {
{ 0b0001, 0b0010, 0b0100, 0b1000, 0b0011, 0b1001, 0b1010, 0b1100 }, { 0b0001, 0b0010, 0b0100, 0b1000, 0b0011, 0b1001, 0b1010, 0b1100 },
{ 0b0111, 0b1011, 0b1101, 0b1110, 0b1111, 0b0000, 0b0000, 0b0000 } { 0b0111, 0b1011, 0b1101, 0b1110, 0b1111, 0b0000, 0b0000, 0b0000 },
}; };
public const bool Sample1DAs2D = true; public const bool Sample1DAs2D = true;
@ -23,7 +22,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
{ {
Texs, Texs,
Tlds, Tlds,
Tld4s Tld4s,
} }
public static void Tex(EmitterContext context) public static void Tex(EmitterContext context)
@ -207,7 +206,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
Operand arrayIndex = isArray ? Ra() : null; Operand arrayIndex = isArray ? Ra() : null;
List<Operand> sourcesList = new List<Operand>(); List<Operand> sourcesList = new();
if (isBindless) if (isBindless)
{ {
@ -353,7 +352,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
return; return;
} }
List<Operand> sourcesList = new List<Operand>(); List<Operand> sourcesList = new();
Operand Ra() Operand Ra()
{ {
@ -722,7 +721,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
Operand arrayIndex = isArray ? Ra() : null; Operand arrayIndex = isArray ? Ra() : null;
List<Operand> sourcesList = new List<Operand>(); List<Operand> sourcesList = new();
SamplerType type = ConvertSamplerType(dimensions); SamplerType type = ConvertSamplerType(dimensions);
TextureFlags flags = TextureFlags.Gather; TextureFlags flags = TextureFlags.Gather;
@ -864,7 +863,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
TextureFlags flags = TextureFlags.None; TextureFlags flags = TextureFlags.None;
List<Operand> sourcesList = new List<Operand>(); List<Operand> sourcesList = new();
if (isBindless) if (isBindless)
{ {
@ -996,7 +995,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
TextureFlags flags = TextureFlags.Derivatives; TextureFlags flags = TextureFlags.Derivatives;
List<Operand> sourcesList = new List<Operand>(); List<Operand> sourcesList = new();
if (isBindless) if (isBindless)
{ {
@ -1126,7 +1125,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
return context.Copy(Register(srcA++, RegisterType.Gpr)); return context.Copy(Register(srcA++, RegisterType.Gpr));
} }
List<Operand> sourcesList = new List<Operand>(); List<Operand> sourcesList = new();
if (isBindless) if (isBindless)
{ {
@ -1195,7 +1194,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
TexDim.Array3d => SamplerType.Texture3D | SamplerType.Array, TexDim.Array3d => SamplerType.Texture3D | SamplerType.Array,
TexDim.Cube => SamplerType.TextureCube, TexDim.Cube => SamplerType.TextureCube,
TexDim.ArrayCube => SamplerType.TextureCube | SamplerType.Array, TexDim.ArrayCube => SamplerType.TextureCube | SamplerType.Array,
_ => throw new ArgumentException($"Invalid texture dimensions \"{dimensions}\".") _ => throw new ArgumentException($"Invalid texture dimensions \"{dimensions}\"."),
}; };
} }

View file

@ -1,7 +1,6 @@
using Ryujinx.Graphics.Shader.Decoders; using Ryujinx.Graphics.Shader.Decoders;
using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
@ -77,7 +76,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
{ {
VideoScale.Shr7 => 7, VideoScale.Shr7 => 7,
VideoScale.Shr15 => 15, VideoScale.Shr15 => 15,
_ => 0 _ => 0,
}; };
if (shift != 0) if (shift != 0)

View file

@ -1,7 +1,6 @@
using Ryujinx.Graphics.Shader.Decoders; using Ryujinx.Graphics.Shader.Decoders;
using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
@ -39,7 +38,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
ShflMode.Up => context.ShuffleUp(srcA, srcB, srcC), ShflMode.Up => context.ShuffleUp(srcA, srcB, srcC),
ShflMode.Down => context.ShuffleDown(srcA, srcB, srcC), ShflMode.Down => context.ShuffleDown(srcA, srcB, srcC),
ShflMode.Bfly => context.ShuffleXor(srcA, srcB, srcC), ShflMode.Bfly => context.ShuffleXor(srcA, srcB, srcC),
_ => (null, null) _ => (null, null),
}; };
context.Copy(GetDest(op.Dest), res); context.Copy(GetDest(op.Dest), res);

View file

@ -1,6 +1,5 @@
using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
namespace Ryujinx.Graphics.Shader.Instructions namespace Ryujinx.Graphics.Shader.Instructions
@ -98,6 +97,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
{ {
return imm switch return imm switch
{ {
#pragma warning disable IDE0055 // Disable formatting
TruthTable.False => Const(0), TruthTable.False => Const(0),
TruthTable.True => Const(-1), TruthTable.True => Const(-1),
TruthTable.In => x, TruthTable.In => x,
@ -118,7 +118,8 @@ namespace Ryujinx.Graphics.Shader.Instructions
TruthTable.AndXor => context.BitwiseExclusiveOr(x, context.BitwiseAnd(y, z)), TruthTable.AndXor => context.BitwiseExclusiveOr(x, context.BitwiseAnd(y, z)),
TruthTable.OrXor => context.BitwiseExclusiveOr(x, context.BitwiseOr(y, z)), TruthTable.OrXor => context.BitwiseExclusiveOr(x, context.BitwiseOr(y, z)),
TruthTable.Xor3 => context.BitwiseExclusiveOr(x, context.BitwiseExclusiveOr(y, z)), TruthTable.Xor3 => context.BitwiseExclusiveOr(x, context.BitwiseExclusiveOr(y, z)),
_ => null _ => null,
#pragma warning restore IDE0055
}; };
} }

View file

@ -83,9 +83,9 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
case Instruction.Discard: case Instruction.Discard:
case Instruction.Return: case Instruction.Return:
return true; return true;
} default:
return false; return false;
} }
} }
} }
}

View file

@ -1,8 +1,10 @@
using System; using System;
using System.Diagnostics.CodeAnalysis;
namespace Ryujinx.Graphics.Shader.IntermediateRepresentation namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
{ {
[Flags] [Flags]
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
enum Instruction enum Instruction
{ {
Absolute = 1, Absolute = 1,
@ -130,7 +132,7 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
FP32 = 1 << 16, FP32 = 1 << 16,
FP64 = 1 << 17, FP64 = 1 << 17,
Mask = 0xffff Mask = 0xffff,
} }
static class InstructionExtensions static class InstructionExtensions

View file

@ -43,6 +43,6 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
VertexId, VertexId,
VertexIndex, VertexIndex,
ViewportIndex, ViewportIndex,
ViewportMask ViewportMask,
} }
} }

View file

@ -8,6 +8,6 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
Label, Label,
LocalVariable, LocalVariable,
Register, Register,
Undefined Undefined,
} }
} }

View file

@ -15,7 +15,7 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
public int DestsCount => _dest != null ? 1 : 0; public int DestsCount => _dest != null ? 1 : 0;
private HashSet<BasicBlock> _blocks; private readonly HashSet<BasicBlock> _blocks;
private class PhiSource private class PhiSource
{ {
@ -29,7 +29,7 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
} }
} }
private List<PhiSource> _sources; private readonly List<PhiSource> _sources;
public int SourcesCount => _sources.Count; public int SourcesCount => _sources.Count;

View file

@ -17,7 +17,7 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
GlobalMemoryS8, // TODO: Remove this and store type as a field on the Operation class itself. GlobalMemoryS8, // TODO: Remove this and store type as a field on the Operation class itself.
GlobalMemoryS16, // TODO: Remove this and store type as a field on the Operation class itself. GlobalMemoryS16, // TODO: Remove this and store type as a field on the Operation class itself.
GlobalMemoryU8, // TODO: Remove this and store type as a field on the Operation class itself. GlobalMemoryU8, // TODO: Remove this and store type as a field on the Operation class itself.
GlobalMemoryU16 // TODO: Remove this and store type as a field on the Operation class itself. GlobalMemoryU16, // TODO: Remove this and store type as a field on the Operation class itself.
} }
static class StorageKindExtensions static class StorageKindExtensions

View file

@ -1,8 +1,10 @@
using System; using System;
using System.Diagnostics.CodeAnalysis;
namespace Ryujinx.Graphics.Shader.IntermediateRepresentation namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
{ {
[Flags] [Flags]
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
enum TextureFlags enum TextureFlags
{ {
None = 0, None = 0,
@ -27,6 +29,6 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
BitwiseOr = 6 << 16, BitwiseOr = 6 << 16,
BitwiseXor = 7 << 16, BitwiseXor = 7 << 16,
Swap = 8 << 16, Swap = 8 << 16,
CAS = 9 << 16 CAS = 9 << 16,
} }
} }

View file

@ -4,21 +4,20 @@ namespace Ryujinx.Graphics.Shader
{ {
PointList = 1, PointList = 1,
LineStrip = 6, LineStrip = 6,
TriangleStrip = 7 TriangleStrip = 7,
} }
static class OutputTopologyExtensions static class OutputTopologyExtensions
{ {
public static string ToGlslString(this OutputTopology topology) public static string ToGlslString(this OutputTopology topology)
{ {
switch (topology) return topology switch
{ {
case OutputTopology.LineStrip: return "line_strip"; OutputTopology.LineStrip => "line_strip",
case OutputTopology.PointList: return "points"; OutputTopology.PointList => "points",
case OutputTopology.TriangleStrip: return "triangle_strip"; OutputTopology.TriangleStrip => "triangle_strip",
} _ => "points",
};
return "points";
} }
} }
} }

View file

@ -18,7 +18,7 @@ namespace Ryujinx.Graphics.Shader
Array = 1 << 8, Array = 1 << 8,
Indexed = 1 << 9, Indexed = 1 << 9,
Multisample = 1 << 10, Multisample = 1 << 10,
Shadow = 1 << 11 Shadow = 1 << 11,
} }
static class SamplerTypeExtensions static class SamplerTypeExtensions
@ -32,7 +32,7 @@ namespace Ryujinx.Graphics.Shader
SamplerType.Texture2D => 2, SamplerType.Texture2D => 2,
SamplerType.Texture3D => 3, SamplerType.Texture3D => 3,
SamplerType.TextureCube => 3, SamplerType.TextureCube => 3,
_ => throw new ArgumentException($"Invalid sampler type \"{type}\".") _ => throw new ArgumentException($"Invalid sampler type \"{type}\"."),
}; };
} }
@ -45,7 +45,7 @@ namespace Ryujinx.Graphics.Shader
SamplerType.Texture2D => "sampler2D", SamplerType.Texture2D => "sampler2D",
SamplerType.Texture3D => "sampler3D", SamplerType.Texture3D => "sampler3D",
SamplerType.TextureCube => "samplerCube", SamplerType.TextureCube => "samplerCube",
_ => throw new ArgumentException($"Invalid sampler type \"{type}\".") _ => throw new ArgumentException($"Invalid sampler type \"{type}\"."),
}; };
if ((type & SamplerType.Multisample) != 0) if ((type & SamplerType.Multisample) != 0)
@ -75,7 +75,7 @@ namespace Ryujinx.Graphics.Shader
SamplerType.Texture2D => "image2D", SamplerType.Texture2D => "image2D",
SamplerType.Texture3D => "image3D", SamplerType.Texture3D => "image3D",
SamplerType.TextureCube => "imageCube", SamplerType.TextureCube => "imageCube",
_ => throw new ArgumentException($"Invalid sampler type \"{type}\".") _ => throw new ArgumentException($"Invalid sampler type \"{type}\"."),
}; };
if ((type & SamplerType.Multisample) != 0) if ((type & SamplerType.Multisample) != 0)
@ -90,8 +90,12 @@ namespace Ryujinx.Graphics.Shader
switch (componentType) switch (componentType)
{ {
case AggregateType.U32: typeName = 'u' + typeName; break; case AggregateType.U32:
case AggregateType.S32: typeName = 'i' + typeName; break; typeName = 'u' + typeName;
break;
case AggregateType.S32:
typeName = 'i' + typeName;
break;
} }
return typeName; return typeName;

View file

@ -3,6 +3,6 @@ namespace Ryujinx.Graphics.Shader
public enum ShaderIdentification public enum ShaderIdentification
{ {
None, None,
GeometryLayerPassthrough GeometryLayerPassthrough,
} }
} }

View file

@ -9,7 +9,7 @@ namespace Ryujinx.Graphics.Shader
Geometry, Geometry,
Fragment, Fragment,
Count Count,
} }
public static class ShaderStageExtensions public static class ShaderStageExtensions

View file

@ -29,7 +29,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
} }
} }
private LinkedList<IAstNode> _nodes; private readonly LinkedList<IAstNode> _nodes;
public IAstNode First => _nodes.First?.Value; public IAstNode First => _nodes.First?.Value;
public IAstNode Last => _nodes.Last?.Value; public IAstNode Last => _nodes.Last?.Value;

View file

@ -7,6 +7,6 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
Else, Else,
ElseIf, ElseIf,
Main, Main,
While While,
} }
} }

View file

@ -49,9 +49,10 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
public static AstOperand Local(AggregateType type) public static AstOperand Local(AggregateType type)
{ {
AstOperand local = new AstOperand(OperandType.LocalVariable); AstOperand local = new(OperandType.LocalVariable)
{
local.VarType = type; VarType = type,
};
return local; return local;
} }

View file

@ -14,7 +14,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
public int Index { get; } public int Index { get; }
private IAstNode[] _sources; private readonly IAstNode[] _sources;
public int SourcesCount => _sources.Length; public int SourcesCount => _sources.Length;
@ -77,9 +77,15 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
switch (componentsCount) switch (componentsCount)
{ {
case 2: type |= AggregateType.Vector2; break; case 2:
case 3: type |= AggregateType.Vector3; break; type |= AggregateType.Vector2;
case 4: type |= AggregateType.Vector4; break; break;
case 3:
type |= AggregateType.Vector3;
break;
case 4:
type |= AggregateType.Vector4;
break;
} }
return type; return type;

View file

@ -17,7 +17,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
// (this makes comparison with the disassembly easier). // (this makes comparison with the disassembly easier).
if (!context.Config.Options.Flags.HasFlag(TranslationFlags.DebugMode)) if (!context.Config.Options.Flags.HasFlag(TranslationFlags.DebugMode))
{ {
AstBlockVisitor visitor = new AstBlockVisitor(mainBlock); AstBlockVisitor visitor = new(mainBlock);
foreach (IAstNode node in visitor.Visit()) foreach (IAstNode node in visitor.Visit())
{ {
@ -45,7 +45,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
private static bool IsWorthPropagating(IAstNode source) private static bool IsWorthPropagating(IAstNode source)
{ {
if (!(source is AstOperation srcOp)) if (source is not AstOperation srcOp)
{ {
return false; return false;
} }
@ -87,7 +87,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
private static void RemoveEmptyBlocks(AstBlock mainBlock) private static void RemoveEmptyBlocks(AstBlock mainBlock)
{ {
Queue<AstBlock> pending = new Queue<AstBlock>(); Queue<AstBlock> pending = new();
pending.Enqueue(mainBlock); pending.Enqueue(mainBlock);

View file

@ -3,6 +3,6 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
enum BufferLayout enum BufferLayout
{ {
Std140, Std140,
Std430 Std430,
} }
} }

View file

@ -1,7 +1,6 @@
using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using static Ryujinx.Graphics.Shader.StructuredIr.AstHelper; using static Ryujinx.Graphics.Shader.StructuredIr.AstHelper;
namespace Ryujinx.Graphics.Shader.StructuredIr namespace Ryujinx.Graphics.Shader.StructuredIr
@ -144,7 +143,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
AstBlock[] path = BackwardsPath(block, ParentBlock(stmt.Label)); AstBlock[] path = BackwardsPath(block, ParentBlock(stmt.Label));
AstBlock loopFirstStmt = path[path.Length - 1]; AstBlock loopFirstStmt = path[^1];
if (loopFirstStmt.Type == AstBlockType.Else) if (loopFirstStmt.Type == AstBlockType.Else)
{ {
@ -265,7 +264,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
else if (child.Type == AstBlockType.Else) else if (child.Type == AstBlockType.Else)
{ {
// Modify the matching if condition to force the else to be entered by the goto. // Modify the matching if condition to force the else to be entered by the goto.
if (!(Previous(child) is AstBlock ifBlock) || ifBlock.Type != AstBlockType.If) if (Previous(child) is not AstBlock ifBlock || ifBlock.Type != AstBlockType.If)
{ {
throw new InvalidOperationException("Found an else without a matching if."); throw new InvalidOperationException("Found an else without a matching if.");
} }
@ -332,7 +331,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
{ {
AstBlock block = ParentBlock(stmt.Goto); AstBlock block = ParentBlock(stmt.Goto);
AstBlock newBlock = new AstBlock(AstBlockType.If, stmt.Condition); AstBlock newBlock = new(AstBlockType.If, stmt.Condition);
block.AddAfter(stmt.Goto, newBlock); block.AddAfter(stmt.Goto, newBlock);
@ -367,7 +366,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
return first as AstBlock; return first as AstBlock;
} }
AstBlock newBlock = new AstBlock(type, cond); AstBlock newBlock = new(type, cond);
block.AddBefore(first, newBlock); block.AddBefore(first, newBlock);
@ -387,7 +386,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
private static bool BlockMatches(IAstNode node, AstBlockType type, IAstNode cond) private static bool BlockMatches(IAstNode node, AstBlockType type, IAstNode cond)
{ {
if (!(node is AstBlock block)) if (node is not AstBlock block)
{ {
return false; return false;
} }
@ -399,7 +398,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
{ {
if (lCond is AstOperation lCondOp && lCondOp.Inst == Instruction.LogicalNot) if (lCond is AstOperation lCondOp && lCondOp.Inst == Instruction.LogicalNot)
{ {
if (!(rCond is AstOperation rCondOp) || rCondOp.Inst != lCondOp.Inst) if (rCond is not AstOperation rCondOp || rCondOp.Inst != lCondOp.Inst)
{ {
return false; return false;
} }
@ -418,7 +417,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
return block.Parent; return block.Parent;
} }
while (!(node is AstBlock)) while (node is not AstBlock)
{ {
node = node.Parent; node = node.Parent;
} }
@ -430,7 +429,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
{ {
AstBlock block = bottom; AstBlock block = bottom;
List<AstBlock> path = new List<AstBlock>(); List<AstBlock> path = new();
while (block != top) while (block != top)
{ {

View file

@ -12,6 +12,6 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
ShuffleUp = 1 << 6, ShuffleUp = 1 << 6,
ShuffleXor = 1 << 7, ShuffleXor = 1 << 7,
SwizzleAdd = 1 << 10, SwizzleAdd = 1 << 10,
FSI = 1 << 11 FSI = 1 << 11,
} }
} }

View file

@ -19,12 +19,13 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
} }
} }
private static InstInfo[] _infoTbl; private static readonly InstInfo[] _infoTbl;
static InstructionInfo() static InstructionInfo()
{ {
_infoTbl = new InstInfo[(int)Instruction.Count]; _infoTbl = new InstInfo[(int)Instruction.Count];
#pragma warning disable IDE0055 // Disable formatting
// Inst Destination type Source 1 type Source 2 type Source 3 type Source 4 type // Inst Destination type Source 1 type Source 2 type Source 3 type Source 4 type
Add(Instruction.AtomicAdd, AggregateType.U32, AggregateType.S32, AggregateType.S32, AggregateType.U32); Add(Instruction.AtomicAdd, AggregateType.U32, AggregateType.S32, AggregateType.S32, AggregateType.U32);
Add(Instruction.AtomicAnd, AggregateType.U32, AggregateType.S32, AggregateType.S32, AggregateType.U32); Add(Instruction.AtomicAnd, AggregateType.U32, AggregateType.S32, AggregateType.S32, AggregateType.U32);
@ -130,6 +131,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
Add(Instruction.VoteAll, AggregateType.Bool, AggregateType.Bool); Add(Instruction.VoteAll, AggregateType.Bool, AggregateType.Bool);
Add(Instruction.VoteAllEqual, AggregateType.Bool, AggregateType.Bool); Add(Instruction.VoteAllEqual, AggregateType.Bool, AggregateType.Bool);
Add(Instruction.VoteAny, AggregateType.Bool, AggregateType.Bool); Add(Instruction.VoteAny, AggregateType.Bool, AggregateType.Bool);
#pragma warning restore IDE0055v
} }
private static void Add(Instruction inst, AggregateType destType, params AggregateType[] srcTypes) private static void Add(Instruction inst, AggregateType destType, params AggregateType[] srcTypes)

View file

@ -25,7 +25,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
OperandType.Argument => AggregateType.S32, OperandType.Argument => AggregateType.S32,
OperandType.Constant => AggregateType.S32, OperandType.Constant => AggregateType.S32,
OperandType.Undefined => AggregateType.S32, OperandType.Undefined => AggregateType.S32,
_ => throw new ArgumentException($"Invalid operand type \"{type}\".") _ => throw new ArgumentException($"Invalid operand type \"{type}\"."),
}; };
} }
} }

View file

@ -30,7 +30,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
BasicBlock srcBlock = phi.GetBlock(index); BasicBlock srcBlock = phi.GetBlock(index);
Operation copyOp = new Operation(Instruction.Copy, phi.Dest, src); Operation copyOp = new(Instruction.Copy, phi.Dest, src);
srcBlock.Append(copyOp); srcBlock.Append(copyOp);
} }

View file

@ -2,7 +2,7 @@ using Ryujinx.Graphics.Shader.Translation;
namespace Ryujinx.Graphics.Shader.StructuredIr namespace Ryujinx.Graphics.Shader.StructuredIr
{ {
struct StructureField readonly struct StructureField
{ {
public AggregateType Type { get; } public AggregateType Type { get; }
public string Name { get; } public string Name { get; }

View file

@ -10,7 +10,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
{ {
public static StructuredProgramInfo MakeStructuredProgram(IReadOnlyList<Function> functions, ShaderConfig config) public static StructuredProgramInfo MakeStructuredProgram(IReadOnlyList<Function> functions, ShaderConfig config)
{ {
StructuredProgramContext context = new StructuredProgramContext(config); StructuredProgramContext context = new(config);
for (int funcIndex = 0; funcIndex < functions.Count; funcIndex++) for (int funcIndex = 0; funcIndex < functions.Count; funcIndex++)
{ {
@ -79,7 +79,6 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
{ {
IoVariable ioVariable = (IoVariable)operation.GetSource(0).Value; IoVariable ioVariable = (IoVariable)operation.GetSource(0).Value;
bool isOutput = storageKind.IsOutput(); bool isOutput = storageKind.IsOutput();
bool perPatch = storageKind.IsPerPatch();
int location = 0; int location = 0;
int component = 0; int component = 0;
@ -169,9 +168,15 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
switch (componentsCount) switch (componentsCount)
{ {
case 2: destType |= AggregateType.Vector2; break; case 2:
case 3: destType |= AggregateType.Vector3; break; destType |= AggregateType.Vector2;
case 4: destType |= AggregateType.Vector4; break; break;
case 3:
destType |= AggregateType.Vector3;
break;
case 4:
destType |= AggregateType.Vector4;
break;
} }
AstOperand destVec = context.NewTemp(destType); AstOperand destVec = context.NewTemp(destType);
@ -181,7 +186,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
for (int i = 0; i < operation.DestsCount; i++) for (int i = 0; i < operation.DestsCount; i++)
{ {
AstOperand dest = context.GetOperand(operation.GetDest(i)); AstOperand dest = context.GetOperand(operation.GetDest(i));
AstOperand index = new AstOperand(OperandType.Constant, i); AstOperand index = new(OperandType.Constant, i);
dest.VarType = destElemType; dest.VarType = destElemType;
@ -304,9 +309,9 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
private static AggregateType GetVarTypeFromUses(Operand dest) private static AggregateType GetVarTypeFromUses(Operand dest)
{ {
HashSet<Operand> visited = new HashSet<Operand>(); HashSet<Operand> visited = new();
Queue<Operand> pending = new Queue<Operand>(); Queue<Operand> pending = new();
bool Enqueue(Operand operand) bool Enqueue(Operand operand)
{ {
@ -385,7 +390,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
{ {
Instruction.ImageLoad or Instruction.ImageLoad or
Instruction.TextureSample => true, Instruction.TextureSample => true,
_ => false _ => false,
}; };
} }
@ -396,7 +401,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
Instruction.Branch or Instruction.Branch or
Instruction.BranchIfFalse or Instruction.BranchIfFalse or
Instruction.BranchIfTrue => true, Instruction.BranchIfTrue => true,
_ => false _ => false,
}; };
} }
@ -408,7 +413,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
Instruction.BitwiseExclusiveOr or Instruction.BitwiseExclusiveOr or
Instruction.BitwiseNot or Instruction.BitwiseNot or
Instruction.BitwiseOr => true, Instruction.BitwiseOr => true,
_ => false _ => false,
}; };
} }
@ -420,7 +425,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
Instruction.BitwiseExclusiveOr => Instruction.LogicalExclusiveOr, Instruction.BitwiseExclusiveOr => Instruction.LogicalExclusiveOr,
Instruction.BitwiseNot => Instruction.LogicalNot, Instruction.BitwiseNot => Instruction.LogicalNot,
Instruction.BitwiseOr => Instruction.LogicalOr, Instruction.BitwiseOr => Instruction.LogicalOr,
_ => throw new ArgumentException($"Unexpected instruction \"{inst}\".") _ => throw new ArgumentException($"Unexpected instruction \"{inst}\"."),
}; };
} }
} }

View file

@ -3,7 +3,6 @@ using Ryujinx.Graphics.Shader.Translation;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Numerics; using System.Numerics;
using static Ryujinx.Graphics.Shader.StructuredIr.AstHelper; using static Ryujinx.Graphics.Shader.StructuredIr.AstHelper;
namespace Ryujinx.Graphics.Shader.StructuredIr namespace Ryujinx.Graphics.Shader.StructuredIr
@ -184,11 +183,11 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
AddNode(Assign(gotoTempAsg.Destination, cond)); AddNode(Assign(gotoTempAsg.Destination, cond));
AstOperation branch = new AstOperation(branchOp.Inst); AstOperation branch = new(branchOp.Inst);
AddNode(branch); AddNode(branch);
GotoStatement gotoStmt = new GotoStatement(branch, gotoTempAsg, isLoop); GotoStatement gotoStmt = new(branch, gotoTempAsg, isLoop);
_gotos.Add(gotoStmt); _gotos.Add(gotoStmt);
} }
@ -236,7 +235,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
private void NewBlock(AstBlockType type, IAstNode cond, int endIndex) private void NewBlock(AstBlockType type, IAstNode cond, int endIndex)
{ {
AstBlock childBlock = new AstBlock(type, cond); AstBlock childBlock = new(type, cond);
AddNode(childBlock); AddNode(childBlock);
@ -316,7 +315,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
new AstOperand(OperandType.Constant, binding), new AstOperand(OperandType.Constant, binding),
new AstOperand(OperandType.Constant, 0), new AstOperand(OperandType.Constant, 0),
new AstOperand(OperandType.Constant, vecIndex), new AstOperand(OperandType.Constant, vecIndex),
new AstOperand(OperandType.Constant, elemIndex) new AstOperand(OperandType.Constant, elemIndex),
}; };
return new AstOperation(Instruction.Load, StorageKind.ConstantBuffer, false, sources, sources.Length); return new AstOperation(Instruction.Load, StorageKind.ConstantBuffer, false, sources, sources.Length);

View file

@ -20,22 +20,22 @@ namespace Ryujinx.Graphics.Shader
FragmentIsBgra, FragmentIsBgra,
ViewportInverse, ViewportInverse,
FragmentRenderScaleCount, FragmentRenderScaleCount,
RenderScale RenderScale,
} }
public struct SupportBuffer public struct SupportBuffer
{ {
internal const int Binding = 0; internal const int Binding = 0;
public static int FieldSize; public static readonly int FieldSize;
public static int RequiredSize; public static readonly int RequiredSize;
public static int FragmentAlphaTestOffset; public static readonly int FragmentAlphaTestOffset;
public static int FragmentIsBgraOffset; public static readonly int FragmentIsBgraOffset;
public static int ViewportInverseOffset; public static readonly int ViewportInverseOffset;
public static int FragmentRenderScaleCountOffset; public static readonly int FragmentRenderScaleCountOffset;
public static int GraphicsRenderScaleOffset; public static readonly int GraphicsRenderScaleOffset;
public static int ComputeRenderScaleOffset; public static readonly int ComputeRenderScaleOffset;
public const int FragmentIsBgraCount = 8; public const int FragmentIsBgraCount = 8;
// One for the render target, 64 for the textures, and 8 for the images. // One for the render target, 64 for the textures, and 8 for the images.
@ -51,7 +51,7 @@ namespace Ryujinx.Graphics.Shader
FieldSize = Unsafe.SizeOf<Vector4<float>>(); FieldSize = Unsafe.SizeOf<Vector4<float>>();
RequiredSize = Unsafe.SizeOf<SupportBuffer>(); RequiredSize = Unsafe.SizeOf<SupportBuffer>();
SupportBuffer instance = new SupportBuffer(); SupportBuffer instance = new();
FragmentAlphaTestOffset = OffsetOf(ref instance, ref instance.FragmentAlphaTest); FragmentAlphaTestOffset = OffsetOf(ref instance, ref instance.FragmentAlphaTest);
FragmentIsBgraOffset = OffsetOf(ref instance, ref instance.FragmentIsBgra); FragmentIsBgraOffset = OffsetOf(ref instance, ref instance.FragmentIsBgra);
@ -69,7 +69,7 @@ namespace Ryujinx.Graphics.Shader
new StructureField(AggregateType.Array | AggregateType.U32, "s_is_bgra", FragmentIsBgraCount), new StructureField(AggregateType.Array | AggregateType.U32, "s_is_bgra", FragmentIsBgraCount),
new StructureField(AggregateType.Vector4 | AggregateType.FP32, "s_viewport_inverse"), new StructureField(AggregateType.Vector4 | AggregateType.FP32, "s_viewport_inverse"),
new StructureField(AggregateType.S32, "s_frag_scale_count"), new StructureField(AggregateType.S32, "s_frag_scale_count"),
new StructureField(AggregateType.Array | AggregateType.FP32, "s_render_scale", RenderScaleMaxCount) new StructureField(AggregateType.Array | AggregateType.FP32, "s_render_scale", RenderScaleMaxCount),
}); });
} }

View file

@ -4,7 +4,7 @@ namespace Ryujinx.Graphics.Shader
{ {
Isolines = 0, Isolines = 0,
Triangles = 1, Triangles = 1,
Quads = 2 Quads = 2,
} }
static class TessPatchTypeExtensions static class TessPatchTypeExtensions
@ -15,7 +15,7 @@ namespace Ryujinx.Graphics.Shader
{ {
TessPatchType.Isolines => "isolines", TessPatchType.Isolines => "isolines",
TessPatchType.Quads => "quads", TessPatchType.Quads => "quads",
_ => "triangles" _ => "triangles",
}; };
} }
} }

View file

@ -4,7 +4,7 @@ namespace Ryujinx.Graphics.Shader
{ {
EqualSpacing = 0, EqualSpacing = 0,
FractionalEventSpacing = 1, FractionalEventSpacing = 1,
FractionalOddSpacing = 2 FractionalOddSpacing = 2,
} }
static class TessSpacingExtensions static class TessSpacingExtensions
@ -15,7 +15,7 @@ namespace Ryujinx.Graphics.Shader
{ {
TessSpacing.FractionalEventSpacing => "fractional_even_spacing", TessSpacing.FractionalEventSpacing => "fractional_even_spacing",
TessSpacing.FractionalOddSpacing => "fractional_odd_spacing", TessSpacing.FractionalOddSpacing => "fractional_odd_spacing",
_ => "equal_spacing" _ => "equal_spacing",
}; };
} }
} }

View file

@ -43,7 +43,7 @@ namespace Ryujinx.Graphics.Shader
R32G32B32A32Sint, R32G32B32A32Sint,
R10G10B10A2Unorm, R10G10B10A2Unorm,
R10G10B10A2Uint, R10G10B10A2Uint,
R11G11B10Float R11G11B10Float,
} }
static class TextureFormatExtensions static class TextureFormatExtensions
@ -52,6 +52,7 @@ namespace Ryujinx.Graphics.Shader
{ {
return format switch return format switch
{ {
#pragma warning disable IDE0055 // Disable formatting
TextureFormat.R8Unorm => "r8", TextureFormat.R8Unorm => "r8",
TextureFormat.R8Snorm => "r8_snorm", TextureFormat.R8Snorm => "r8_snorm",
TextureFormat.R8Uint => "r8ui", TextureFormat.R8Uint => "r8ui",
@ -91,7 +92,8 @@ namespace Ryujinx.Graphics.Shader
TextureFormat.R10G10B10A2Unorm => "rgb10_a2", TextureFormat.R10G10B10A2Unorm => "rgb10_a2",
TextureFormat.R10G10B10A2Uint => "rgb10_a2ui", TextureFormat.R10G10B10A2Uint => "rgb10_a2ui",
TextureFormat.R11G11B10Float => "r11f_g11f_b10f", TextureFormat.R11G11B10Float => "r11f_g11f_b10f",
_ => string.Empty _ => string.Empty,
#pragma warning restore IDE0055
}; };
} }

View file

@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.Shader
CombinedSampler = 0, // Must be 0. CombinedSampler = 0, // Must be 0.
SeparateSamplerHandle = 1, SeparateSamplerHandle = 1,
SeparateSamplerId = 2, SeparateSamplerId = 2,
SeparateConstantSamplerHandle = 3 SeparateConstantSamplerHandle = 3,
} }
public static class TextureHandle public static class TextureHandle

View file

@ -14,6 +14,6 @@ namespace Ryujinx.Graphics.Shader
ResScaleUnsupported = 1 << 0, ResScaleUnsupported = 1 << 0,
NeedsScaleValue = 1 << 1, NeedsScaleValue = 1 << 1,
ImageStore = 1 << 2, ImageStore = 1 << 2,
ImageCoherent = 1 << 3 ImageCoherent = 1 << 3,
} }
} }

View file

@ -1,8 +1,10 @@
using System; using System;
using System.Diagnostics.CodeAnalysis;
namespace Ryujinx.Graphics.Shader.Translation namespace Ryujinx.Graphics.Shader.Translation
{ {
[Flags] [Flags]
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
enum AggregateType enum AggregateType
{ {
Invalid, Invalid,
@ -23,7 +25,7 @@ namespace Ryujinx.Graphics.Shader.Translation
Vector3 = 2 << ElementCountShift, Vector3 = 2 << ElementCountShift,
Vector4 = 3 << ElementCountShift, Vector4 = 3 << ElementCountShift,
Array = 1 << 10 Array = 1 << 10,
} }
static class AggregateTypeExtensions static class AggregateTypeExtensions
@ -37,7 +39,7 @@ namespace Ryujinx.Graphics.Shader.Translation
AggregateType.S32 or AggregateType.S32 or
AggregateType.U32 => 4, AggregateType.U32 => 4,
AggregateType.FP64 => 8, AggregateType.FP64 => 8,
_ => 0 _ => 0,
}; };
switch (type & AggregateType.ElementCountMask) switch (type & AggregateType.ElementCountMask)

View file

@ -13,11 +13,11 @@ namespace Ryujinx.Graphics.Shader.Translation
{ {
Blocks = blocks; Blocks = blocks;
HashSet<BasicBlock> visited = new HashSet<BasicBlock>(); HashSet<BasicBlock> visited = new();
Stack<BasicBlock> blockStack = new Stack<BasicBlock>(); Stack<BasicBlock> blockStack = new();
List<BasicBlock> postOrderBlocks = new List<BasicBlock>(blocks.Length); List<BasicBlock> postOrderBlocks = new(blocks.Length);
PostOrderMap = new int[blocks.Length]; PostOrderMap = new int[blocks.Length];
@ -50,9 +50,9 @@ namespace Ryujinx.Graphics.Shader.Translation
public static ControlFlowGraph Create(Operation[] operations) public static ControlFlowGraph Create(Operation[] operations)
{ {
Dictionary<Operand, BasicBlock> labels = new Dictionary<Operand, BasicBlock>(); Dictionary<Operand, BasicBlock> labels = new();
List<BasicBlock> blocks = new List<BasicBlock>(); List<BasicBlock> blocks = new();
BasicBlock currentBlock = null; BasicBlock currentBlock = null;
@ -68,7 +68,7 @@ namespace Ryujinx.Graphics.Shader.Translation
void NewNextBlock() void NewNextBlock()
{ {
BasicBlock block = new BasicBlock(blocks.Count); BasicBlock block = new(blocks.Count);
blocks.Add(block); blocks.Add(block);

View file

@ -4,7 +4,6 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
namespace Ryujinx.Graphics.Shader.Translation namespace Ryujinx.Graphics.Shader.Translation
@ -84,7 +83,7 @@ namespace Ryujinx.Graphics.Shader.Translation
public Operand Add(Instruction inst, Operand dest = null, params Operand[] sources) public Operand Add(Instruction inst, Operand dest = null, params Operand[] sources)
{ {
Operation operation = new Operation(inst, dest, sources); Operation operation = new(inst, dest, sources);
_operations.Add(operation); _operations.Add(operation);
@ -93,7 +92,7 @@ namespace Ryujinx.Graphics.Shader.Translation
public Operand Add(Instruction inst, StorageKind storageKind, Operand dest = null, params Operand[] sources) public Operand Add(Instruction inst, StorageKind storageKind, Operand dest = null, params Operand[] sources)
{ {
Operation operation = new Operation(inst, storageKind, dest, sources); Operation operation = new(inst, storageKind, dest, sources);
_operations.Add(operation); _operations.Add(operation);
@ -104,7 +103,7 @@ namespace Ryujinx.Graphics.Shader.Translation
{ {
Operand[] dests = new[] { dest.Item1, dest.Item2 }; Operand[] dests = new[] { dest.Item1, dest.Item2 };
Operation operation = new Operation(inst, 0, dests, sources); Operation operation = new(inst, 0, dests, sources);
Add(operation); Add(operation);
@ -430,7 +429,7 @@ namespace Ryujinx.Graphics.Shader.Translation
AlphaTestOp.Less => Instruction.CompareLess, AlphaTestOp.Less => Instruction.CompareLess,
AlphaTestOp.LessOrEqual => Instruction.CompareLessOrEqual, AlphaTestOp.LessOrEqual => Instruction.CompareLessOrEqual,
AlphaTestOp.NotEqual => Instruction.CompareNotEqual, AlphaTestOp.NotEqual => Instruction.CompareNotEqual,
_ => 0 _ => 0,
}; };
Debug.Assert(comparator != 0, $"Invalid alpha test operation \"{alphaTestOp}\"."); Debug.Assert(comparator != 0, $"Invalid alpha test operation \"{alphaTestOp}\".");

View file

@ -23,6 +23,6 @@ namespace Ryujinx.Graphics.Shader.Translation
OaIndexing = 1 << 8, OaIndexing = 1 << 8,
FixedFuncAttr = 1 << 9, FixedFuncAttr = 1 << 9,
LocalMemory = 1 << 10, LocalMemory = 1 << 10,
SharedMemory = 1 << 11 SharedMemory = 1 << 11,
} }
} }

View file

@ -7,11 +7,11 @@ namespace Ryujinx.Graphics.Shader.Translation
{ {
static class FunctionMatch static class FunctionMatch
{ {
private static IPatternTreeNode[] _fsiGetAddressTree = PatternTrees.GetFsiGetAddress(); private static readonly IPatternTreeNode[] _fsiGetAddressTree = PatternTrees.GetFsiGetAddress();
private static IPatternTreeNode[] _fsiGetAddressV2Tree = PatternTrees.GetFsiGetAddressV2(); private static readonly IPatternTreeNode[] _fsiGetAddressV2Tree = PatternTrees.GetFsiGetAddressV2();
private static IPatternTreeNode[] _fsiIsLastWarpThreadPatternTree = PatternTrees.GetFsiIsLastWarpThread(); private static readonly IPatternTreeNode[] _fsiIsLastWarpThreadPatternTree = PatternTrees.GetFsiIsLastWarpThread();
private static IPatternTreeNode[] _fsiBeginPatternTree = PatternTrees.GetFsiBeginPattern(); private static readonly IPatternTreeNode[] _fsiBeginPatternTree = PatternTrees.GetFsiBeginPattern();
private static IPatternTreeNode[] _fsiEndPatternTree = PatternTrees.GetFsiEndPattern(); private static readonly IPatternTreeNode[] _fsiEndPatternTree = PatternTrees.GetFsiEndPattern();
public static void RunPass(DecodedProgram program) public static void RunPass(DecodedProgram program)
{ {
@ -113,7 +113,7 @@ namespace Ryujinx.Graphics.Shader.Translation
private enum TreeNodeType : byte private enum TreeNodeType : byte
{ {
Op, Op,
Label Label,
} }
private class TreeNode private class TreeNode
@ -150,9 +150,9 @@ namespace Ryujinx.Graphics.Shader.Translation
private static TreeNode[] BuildTree(Block[] blocks) private static TreeNode[] BuildTree(Block[] blocks)
{ {
List<TreeNode> nodes = new List<TreeNode>(); List<TreeNode> nodes = new();
Dictionary<ulong, TreeNode> labels = new Dictionary<ulong, TreeNode>(); Dictionary<ulong, TreeNode> labels = new();
TreeNodeUse[] predDefs = new TreeNodeUse[RegisterConsts.PredsCount]; TreeNodeUse[] predDefs = new TreeNodeUse[RegisterConsts.PredsCount];
TreeNodeUse[] gprDefs = new TreeNodeUse[RegisterConsts.GprsCount]; TreeNodeUse[] gprDefs = new TreeNodeUse[RegisterConsts.GprsCount];
@ -223,7 +223,7 @@ namespace Ryujinx.Graphics.Shader.Translation
if (block.Predecessors.Count > 1) if (block.Predecessors.Count > 1)
{ {
TreeNode label = new TreeNode(order++); TreeNode label = new(order++);
nodes.Add(label); nodes.Add(label);
labels.Add(block.Address, label); labels.Add(block.Address, label);
} }
@ -232,7 +232,7 @@ namespace Ryujinx.Graphics.Shader.Translation
{ {
InstOp op = block.OpCodes[opIndex]; InstOp op = block.OpCodes[opIndex];
TreeNode node = new TreeNode(op, IsOrderDependant(op.Name) ? order : (byte)0); TreeNode node = new(op, IsOrderDependant(op.Name) ? order : (byte)0);
// Add uses. // Add uses.
@ -288,7 +288,7 @@ namespace Ryujinx.Graphics.Shader.Translation
InstProps.SPd => 30, InstProps.SPd => 30,
InstProps.TPd => 51, InstProps.TPd => 51,
InstProps.VPd => 45, InstProps.VPd => 45,
_ => throw new InvalidOperationException($"Table has unknown predicate destination {pdType}.") _ => throw new InvalidOperationException($"Table has unknown predicate destination {pdType}."),
}; };
byte predIndex = (byte)((op.RawOpCode >> bit) & 7); byte predIndex = (byte)((op.RawOpCode >> bit) & 7);
@ -350,7 +350,7 @@ namespace Ryujinx.Graphics.Shader.Translation
public IPatternTreeNode Node { get; } public IPatternTreeNode Node { get; }
public int Index { get; } public int Index { get; }
public bool Inverted { get; } public bool Inverted { get; }
public PatternTreeNodeUse Inv => new PatternTreeNodeUse(Index, !Inverted, Node); public PatternTreeNodeUse Inv => new(Index, !Inverted, Node);
private PatternTreeNodeUse(int index, bool inverted, IPatternTreeNode node) private PatternTreeNodeUse(int index, bool inverted, IPatternTreeNode node)
{ {
@ -373,7 +373,7 @@ namespace Ryujinx.Graphics.Shader.Translation
public TreeNodeType Type { get; } public TreeNodeType Type { get; }
public byte Order { get; } public byte Order { get; }
public bool IsImm { get; } public bool IsImm { get; }
public PatternTreeNodeUse Out => new PatternTreeNodeUse(0, this); public PatternTreeNodeUse Out => new(0, this);
public PatternTreeNode(InstName name, Func<T, bool> match, TreeNodeType type = TreeNodeType.Op, byte order = 0, bool isImm = false) public PatternTreeNode(InstName name, Func<T, bool> match, TreeNodeType type = TreeNodeType.Op, byte order = 0, bool isImm = false)
{ {
@ -435,7 +435,7 @@ namespace Ryujinx.Graphics.Shader.Translation
} }
DecodedFunction callTarget = program.GetFunctionByAddress(callOp.GetAbsoluteAddress()); DecodedFunction callTarget = program.GetFunctionByAddress(callOp.GetAbsoluteAddress());
TreeNode[] callTargetTree = null; TreeNode[] callTargetTree;
if (callTarget == null || !Matches(_fsiIsLastWarpThreadPatternTree, callTargetTree = BuildTree(callTarget.Blocks))) if (callTarget == null || !Matches(_fsiIsLastWarpThreadPatternTree, callTargetTree = BuildTree(callTarget.Blocks)))
{ {
@ -548,7 +548,7 @@ namespace Ryujinx.Graphics.Shader.Translation
.Use(PT) .Use(PT)
.Use(orderingTicketValue).Out), .Use(orderingTicketValue).Out),
Iadd(x: true, 0, 405).Use(PT).Use(RZ), Iadd(x: true, 0, 405).Use(PT).Use(RZ),
Ret().Use(PT) Ret().Use(PT),
}; };
} }
@ -576,7 +576,7 @@ namespace Ryujinx.Graphics.Shader.Translation
.Use(PT) .Use(PT)
.Use(orderingTicketValue).Out).Out), .Use(orderingTicketValue).Out).Out),
Iadd(x: true, 0, 405).Use(PT).Use(RZ), Iadd(x: true, 0, 405).Use(PT).Use(RZ),
Ret().Use(PT) Ret().Use(PT),
}; };
} }
@ -603,7 +603,7 @@ namespace Ryujinx.Graphics.Shader.Translation
.Use(threadKillValue).OutAt(1)) .Use(threadKillValue).OutAt(1))
.Use(RZ).Out).OutAt(1)).Out) .Use(RZ).Out).OutAt(1)).Out)
.Use(laneIdValue), .Use(laneIdValue),
Ret().Use(PT) Ret().Use(PT),
}; };
} }
@ -638,7 +638,7 @@ namespace Ryujinx.Graphics.Shader.Translation
.Use(PT) .Use(PT)
.Use(addressLowValue).Out).Inv) .Use(addressLowValue).Out).Inv)
.Use(label.Out), .Use(label.Out),
Ret().Use(PT) Ret().Use(PT),
}; };
} }
@ -684,7 +684,7 @@ namespace Ryujinx.Graphics.Shader.Translation
.Use(incrementValue) .Use(incrementValue)
.Use(popcResult) .Use(popcResult)
.Use(RZ).Out).Out), .Use(RZ).Out).Out),
Ret().Use(PT) Ret().Use(PT),
}; };
} }
@ -806,7 +806,6 @@ namespace Ryujinx.Graphics.Shader.Translation
private static PatternTreeNodeUse PT => PTOrRZ(); private static PatternTreeNodeUse PT => PTOrRZ();
private static PatternTreeNodeUse RZ => PTOrRZ(); private static PatternTreeNodeUse RZ => PTOrRZ();
private static PatternTreeNodeUse Undef => new PatternTreeNodeUse(0, null);
private static PatternTreeNodeUse CallArg(int index) private static PatternTreeNodeUse CallArg(int index)
{ {

View file

@ -1,7 +1,6 @@
using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
namespace Ryujinx.Graphics.Shader.Translation namespace Ryujinx.Graphics.Shader.Translation
@ -65,13 +64,13 @@ namespace Ryujinx.Graphics.Shader.Translation
HelperFunctionName.ConvertFloatToDouble => GenerateConvertFloatToDoubleFunction(), HelperFunctionName.ConvertFloatToDouble => GenerateConvertFloatToDoubleFunction(),
HelperFunctionName.TexelFetchScale => GenerateTexelFetchScaleFunction(), HelperFunctionName.TexelFetchScale => GenerateTexelFetchScaleFunction(),
HelperFunctionName.TextureSizeUnscale => GenerateTextureSizeUnscaleFunction(), HelperFunctionName.TextureSizeUnscale => GenerateTextureSizeUnscaleFunction(),
_ => throw new ArgumentException($"Invalid function name {functionName}") _ => throw new ArgumentException($"Invalid function name {functionName}"),
}; };
} }
private Function GenerateConvertDoubleToFloatFunction() private static Function GenerateConvertDoubleToFloatFunction()
{ {
EmitterContext context = new EmitterContext(); EmitterContext context = new();
Operand valueLow = Argument(0); Operand valueLow = Argument(0);
Operand valueHigh = Argument(1); Operand valueHigh = Argument(1);
@ -119,9 +118,9 @@ namespace Ryujinx.Graphics.Shader.Translation
return new Function(ControlFlowGraph.Create(context.GetOperations()).Blocks, "ConvertDoubleToFloat", true, 2, 0); return new Function(ControlFlowGraph.Create(context.GetOperations()).Blocks, "ConvertDoubleToFloat", true, 2, 0);
} }
private Function GenerateConvertFloatToDoubleFunction() private static Function GenerateConvertFloatToDoubleFunction()
{ {
EmitterContext context = new EmitterContext(); EmitterContext context = new();
Operand value = Argument(0); Operand value = Argument(0);
@ -164,13 +163,13 @@ namespace Ryujinx.Graphics.Shader.Translation
HelperFunctionName.SharedAtomicMinS32 => GenerateSharedAtomicSigned(id, isMin: true), HelperFunctionName.SharedAtomicMinS32 => GenerateSharedAtomicSigned(id, isMin: true),
HelperFunctionName.SharedStore8 => GenerateSharedStore8(id), HelperFunctionName.SharedStore8 => GenerateSharedStore8(id),
HelperFunctionName.SharedStore16 => GenerateSharedStore16(id), HelperFunctionName.SharedStore16 => GenerateSharedStore16(id),
_ => throw new ArgumentException($"Invalid function name {functionName}") _ => throw new ArgumentException($"Invalid function name {functionName}"),
}; };
} }
private static Function GenerateSharedAtomicSigned(int id, bool isMin) private static Function GenerateSharedAtomicSigned(int id, bool isMin)
{ {
EmitterContext context = new EmitterContext(); EmitterContext context = new();
Operand wordOffset = Argument(0); Operand wordOffset = Argument(0);
Operand value = Argument(1); Operand value = Argument(1);
@ -199,7 +198,7 @@ namespace Ryujinx.Graphics.Shader.Translation
private static Function GenerateSharedStore(int id, int bitSize) private static Function GenerateSharedStore(int id, int bitSize)
{ {
EmitterContext context = new EmitterContext(); EmitterContext context = new();
Operand offset = Argument(0); Operand offset = Argument(0);
Operand value = Argument(1); Operand value = Argument(1);
@ -219,7 +218,7 @@ namespace Ryujinx.Graphics.Shader.Translation
private Function GenerateTexelFetchScaleFunction() private Function GenerateTexelFetchScaleFunction()
{ {
EmitterContext context = new EmitterContext(); EmitterContext context = new();
Operand input = Argument(0); Operand input = Argument(0);
Operand samplerIndex = Argument(1); Operand samplerIndex = Argument(1);
@ -270,7 +269,7 @@ namespace Ryujinx.Graphics.Shader.Translation
private Function GenerateTextureSizeUnscaleFunction() private Function GenerateTextureSizeUnscaleFunction()
{ {
EmitterContext context = new EmitterContext(); EmitterContext context = new();
Operand input = Argument(0); Operand input = Argument(0);
Operand samplerIndex = Argument(1); Operand samplerIndex = Argument(1);

View file

@ -9,6 +9,6 @@ namespace Ryujinx.Graphics.Shader.Translation
SharedStore8, SharedStore8,
SharedStore16, SharedStore16,
TexelFetchScale, TexelFetchScale,
TextureSizeUnscale TextureSizeUnscale,
} }
} }

View file

@ -16,7 +16,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
// - Both sources of the OR operation comes from a constant buffer. // - Both sources of the OR operation comes from a constant buffer.
for (LinkedListNode<INode> node = block.Operations.First; node != null; node = node.Next) for (LinkedListNode<INode> node = block.Operations.First; node != null; node = node.Next)
{ {
if (!(node.Value is TextureOperation texOp)) if (node.Value is not TextureOperation texOp)
{ {
continue; continue;
} }
@ -47,7 +47,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
continue; continue;
} }
if (!(bindlessHandle.AsgOp is Operation handleCombineOp)) if (bindlessHandle.AsgOp is not Operation handleCombineOp)
{ {
continue; continue;
} }
@ -66,9 +66,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
// and having a "canonical" representation simplifies some checks below. // and having a "canonical" representation simplifies some checks below.
if (src0.Type == OperandType.Constant && src1.Type != OperandType.Constant) if (src0.Type == OperandType.Constant && src1.Type != OperandType.Constant)
{ {
Operand temp = src1; (src0, src1) = (src1, src0);
src1 = src0;
src0 = temp;
} }
TextureHandleType handleType = TextureHandleType.SeparateSamplerHandle; TextureHandleType handleType = TextureHandleType.SeparateSamplerHandle;

View file

@ -17,7 +17,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
// The base offset of the array of handles on the constant buffer is the constant offset. // The base offset of the array of handles on the constant buffer is the constant offset.
for (LinkedListNode<INode> node = block.Operations.First; node != null; node = node.Next) for (LinkedListNode<INode> node = block.Operations.First; node != null; node = node.Next)
{ {
if (!(node.Value is TextureOperation texOp)) if (node.Value is not TextureOperation texOp)
{ {
continue; continue;
} }
@ -27,7 +27,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
continue; continue;
} }
if (!(texOp.GetSource(0).AsgOp is Operation handleAsgOp)) if (texOp.GetSource(0).AsgOp is not Operation handleAsgOp)
{ {
continue; continue;
} }
@ -64,17 +64,17 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
// Plus this whole transform is fundamentally flawed as-is since we have no way to know the array size. // Plus this whole transform is fundamentally flawed as-is since we have no way to know the array size.
// Eventually, this should be entirely removed in favor of a implementation that supports true bindless // Eventually, this should be entirely removed in favor of a implementation that supports true bindless
// texture access. // texture access.
if (!(ldcSrc2.AsgOp is Operation shrOp) || shrOp.Inst != Instruction.ShiftRightU32) if (ldcSrc2.AsgOp is not Operation shrOp || shrOp.Inst != Instruction.ShiftRightU32)
{ {
continue; continue;
} }
if (!(shrOp.GetSource(0).AsgOp is Operation shrOp2) || shrOp2.Inst != Instruction.ShiftRightU32) if (shrOp.GetSource(0).AsgOp is not Operation shrOp2 || shrOp2.Inst != Instruction.ShiftRightU32)
{ {
continue; continue;
} }
if (!(shrOp2.GetSource(0).AsgOp is Operation addOp) || addOp.Inst != Instruction.Add) if (shrOp2.GetSource(0).AsgOp is not Operation addOp || addOp.Inst != Instruction.Add)
{ {
continue; continue;
} }
@ -92,7 +92,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
Operand source = addOp.GetSource(0); Operand source = addOp.GetSource(0);
Operation shrBy3 = new Operation(Instruction.ShiftRightU32, index, source, Const(3)); Operation shrBy3 = new(Instruction.ShiftRightU32, index, source, Const(3));
block.Operations.AddBefore(node, shrBy3); block.Operations.AddBefore(node, shrBy3);

View file

@ -31,7 +31,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
return false; return false;
} }
if (!(nextBlock.Operations.First?.Value is Operation next)) if (nextBlock.Operations.First?.Value is not Operation next)
{ {
return false; return false;
} }

View file

@ -1,7 +1,6 @@
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using System; using System;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
namespace Ryujinx.Graphics.Shader.Translation.Optimizations namespace Ryujinx.Graphics.Shader.Translation.Optimizations
@ -278,13 +277,6 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
operation.TurnIntoCopy(ConstF((float)BitConverter.UInt16BitsToHalf((ushort)value))); operation.TurnIntoCopy(ConstF((float)BitConverter.UInt16BitsToHalf((ushort)value)));
} }
private static void FPNegate(Operation operation)
{
float value = operation.GetSource(0).AsFloat();
operation.TurnIntoCopy(ConstF(-value));
}
private static void EvaluateUnary(Operation operation, Func<int, int> op) private static void EvaluateUnary(Operation operation, Func<int, int> op)
{ {
int x = operation.GetSource(0).Value; int x = operation.GetSource(0).Value;

View file

@ -11,7 +11,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
{ {
for (LinkedListNode<INode> node = block.Operations.First; node != null; node = node.Next) for (LinkedListNode<INode> node = block.Operations.First; node != null; node = node.Next)
{ {
if (node.Value is not Operation operation) if (node.Value is not Operation)
{ {
continue; continue;
} }

View file

@ -2,7 +2,6 @@ using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
namespace Ryujinx.Graphics.Shader.Translation.Optimizations namespace Ryujinx.Graphics.Shader.Translation.Optimizations
@ -14,12 +13,12 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
enum LsMemoryType enum LsMemoryType
{ {
Local, Local,
Shared Shared,
} }
private class GtsContext private class GtsContext
{ {
private struct Entry private readonly struct Entry
{ {
public readonly int FunctionId; public readonly int FunctionId;
public readonly Instruction Inst; public readonly Instruction Inst;
@ -42,7 +41,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
} }
} }
private struct LsKey : IEquatable<LsKey> private readonly struct LsKey : IEquatable<LsKey>
{ {
public readonly Operand BaseOffset; public readonly Operand BaseOffset;
public readonly int ConstOffset; public readonly int ConstOffset;
@ -127,7 +126,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
public void AddMemoryTargetCb(LsMemoryType type, Operand baseOffset, int constOffset, uint targetCb, SearchResult result) public void AddMemoryTargetCb(LsMemoryType type, Operand baseOffset, int constOffset, uint targetCb, SearchResult result)
{ {
LsKey key = new LsKey(baseOffset, constOffset, type); LsKey key = new(baseOffset, constOffset, type);
if (!_sharedEntries.TryGetValue(key, out Dictionary<uint, SearchResult> targetCbs)) if (!_sharedEntries.TryGetValue(key, out Dictionary<uint, SearchResult> targetCbs))
{ {
@ -162,7 +161,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
public bool TryGetMemoryTargetCb(LsMemoryType type, Operand baseOffset, int constOffset, out SearchResult result) public bool TryGetMemoryTargetCb(LsMemoryType type, Operand baseOffset, int constOffset, out SearchResult result)
{ {
LsKey key = new LsKey(baseOffset, constOffset, type); LsKey key = new(baseOffset, constOffset, type);
if (_sharedEntries.TryGetValue(key, out Dictionary<uint, SearchResult> targetCbs) && targetCbs.Count == 1) if (_sharedEntries.TryGetValue(key, out Dictionary<uint, SearchResult> targetCbs) && targetCbs.Count == 1)
{ {
@ -182,9 +181,9 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
} }
} }
private struct SearchResult private readonly struct SearchResult
{ {
public static SearchResult NotFound => new SearchResult(-1, 0); public static SearchResult NotFound => new(-1, 0);
public bool Found => SbCbSlot != -1; public bool Found => SbCbSlot != -1;
public int SbCbSlot { get; } public int SbCbSlot { get; }
public int SbCbOffset { get; } public int SbCbOffset { get; }
@ -208,13 +207,13 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
public static void RunPass(HelperFunctionManager hfm, BasicBlock[] blocks, ShaderConfig config) public static void RunPass(HelperFunctionManager hfm, BasicBlock[] blocks, ShaderConfig config)
{ {
GtsContext gtsContext = new GtsContext(hfm); GtsContext gtsContext = new(hfm);
foreach (BasicBlock block in blocks) foreach (BasicBlock block in blocks)
{ {
for (LinkedListNode<INode> node = block.Operations.First; node != null; node = node.Next) for (LinkedListNode<INode> node = block.Operations.First; node != null; node = node.Next)
{ {
if (!(node.Value is Operation operation)) if (node.Value is not Operation operation)
{ {
continue; continue;
} }
@ -315,8 +314,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
int alignment = config.GpuAccessor.QueryHostStorageBufferOffsetAlignment(); int alignment = config.GpuAccessor.QueryHostStorageBufferOffsetAlignment();
Operation maskOp = new Operation(Instruction.BitwiseAnd, baseAddressMasked, new[] { baseAddress, Const(-alignment) }); Operation maskOp = new(Instruction.BitwiseAnd, baseAddressMasked, baseAddress, Const(-alignment));
Operation subOp = new Operation(Instruction.Subtract, hostOffset, new[] { globalAddress, baseAddressMasked }); Operation subOp = new(Instruction.Subtract, hostOffset, globalAddress, baseAddressMasked);
node.List.AddBefore(node, maskOp); node.List.AddBefore(node, maskOp);
node.List.AddBefore(node, subOp); node.List.AddBefore(node, subOp);
@ -327,7 +326,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
{ {
Operand newOffset = Local(); Operand newOffset = Local();
Operation addOp = new Operation(Instruction.Add, newOffset, new[] { offset, Const(result.ConstOffset) }); Operation addOp = new(Instruction.Add, newOffset, offset, Const(result.ConstOffset));
node.List.AddBefore(node, addOp); node.List.AddBefore(node, addOp);
@ -394,26 +393,26 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
if (operation.Inst == Instruction.AtomicCompareAndSwap) if (operation.Inst == Instruction.AtomicCompareAndSwap)
{ {
sources = new Operand[] sources = new[]
{ {
Const(binding), Const(binding),
Const(0), Const(0),
wordOffset, wordOffset,
operation.GetSource(operation.SourcesCount - 2), operation.GetSource(operation.SourcesCount - 2),
operation.GetSource(operation.SourcesCount - 1) operation.GetSource(operation.SourcesCount - 1),
}; };
} }
else if (isStore) else if (isStore)
{ {
sources = new Operand[] { Const(binding), Const(0), wordOffset, operation.GetSource(operation.SourcesCount - 1) }; sources = new[] { Const(binding), Const(0), wordOffset, operation.GetSource(operation.SourcesCount - 1) };
} }
else else
{ {
sources = new Operand[] { Const(binding), Const(0), wordOffset }; sources = new[] { Const(binding), Const(0), wordOffset };
} }
Operation shiftOp = new Operation(Instruction.ShiftRightU32, wordOffset, new[] { offset, Const(2) }); Operation shiftOp = new(Instruction.ShiftRightU32, wordOffset, offset, Const(2));
Operation storageOp = new Operation(operation.Inst, StorageKind.StorageBuffer, operation.Dest, sources); Operation storageOp = new(operation.Inst, StorageKind.StorageBuffer, operation.Dest, sources);
node.List.AddBefore(node, shiftOp); node.List.AddBefore(node, shiftOp);
LinkedListNode<INode> newNode = node.List.AddBefore(node, storageOp); LinkedListNode<INode> newNode = node.List.AddBefore(node, storageOp);
@ -455,7 +454,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
bool returnsValue = operation.Dest != null; bool returnsValue = operation.Dest != null;
Operand returnValue = returnsValue ? Local() : null; Operand returnValue = returnsValue ? Local() : null;
Operation callOp = new Operation(Instruction.Call, returnValue, sources); Operation callOp = new(Instruction.Call, returnValue, sources);
LinkedListNode<INode> newNode = node.List.AddBefore(node, callOp); LinkedListNode<INode> newNode = node.List.AddBefore(node, callOp);
@ -480,7 +479,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
SearchResult result, SearchResult result,
out int functionId) out int functionId)
{ {
List<uint> targetCbs = new List<uint>() { PackCbSlotAndOffset(result.SbCbSlot, result.SbCbOffset) }; List<uint> targetCbs = new() { PackCbSlotAndOffset(result.SbCbSlot, result.SbCbOffset) };
if (gtsContext.TryGetFunctionId(operation, isMultiTarget: false, targetCbs, out functionId)) if (gtsContext.TryGetFunctionId(operation, isMultiTarget: false, targetCbs, out functionId))
{ {
@ -498,7 +497,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
inArgumentsCount = 2; inArgumentsCount = 2;
} }
EmitterContext context = new EmitterContext(); EmitterContext context = new();
Operand offset = Argument(0); Operand offset = Argument(0);
Operand compare = null; Operand compare = null;
@ -542,7 +541,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
string functionName = GetFunctionName(operation, isMultiTarget: false, targetCbs); string functionName = GetFunctionName(operation, isMultiTarget: false, targetCbs);
Function function = new Function( Function function = new(
ControlFlowGraph.Create(context.GetOperations()).Blocks, ControlFlowGraph.Create(context.GetOperations()).Blocks,
functionName, functionName,
returnsValue, returnsValue,
@ -561,9 +560,9 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
Operation operation, Operation operation,
out int functionId) out int functionId)
{ {
Queue<PhiNode> phis = new Queue<PhiNode>(); Queue<PhiNode> phis = new();
HashSet<PhiNode> visited = new HashSet<PhiNode>(); HashSet<PhiNode> visited = new();
List<uint> targetCbs = new List<uint>(); List<uint> targetCbs = new();
Operand globalAddress = operation.GetSource(0); Operand globalAddress = operation.GetSource(0);
@ -644,7 +643,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
inArgumentsCount = 3; inArgumentsCount = 3;
} }
EmitterContext context = new EmitterContext(); EmitterContext context = new();
Operand globalAddressLow = Argument(0); Operand globalAddressLow = Argument(0);
Operand globalAddressHigh = Argument(1); Operand globalAddressHigh = Argument(1);
@ -684,7 +683,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
value = Argument(2); value = Argument(2);
} }
SearchResult result = new SearchResult(sbCbSlot, sbCbOffset); SearchResult result = new(sbCbSlot, sbCbOffset);
int alignment = config.GpuAccessor.QueryHostStorageBufferOffsetAlignment(); int alignment = config.GpuAccessor.QueryHostStorageBufferOffsetAlignment();
@ -731,7 +730,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
string functionName = GetFunctionName(operation, isMultiTarget: true, targetCbs); string functionName = GetFunctionName(operation, isMultiTarget: true, targetCbs);
Function function = new Function( Function function = new(
ControlFlowGraph.Create(context.GetOperations()).Blocks, ControlFlowGraph.Create(context.GetOperations()).Blocks,
functionName, functionName,
returnsValue, returnsValue,
@ -763,7 +762,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
StorageKind.GlobalMemoryS16 => "S16", StorageKind.GlobalMemoryS16 => "S16",
StorageKind.GlobalMemoryU8 => "U8", StorageKind.GlobalMemoryU8 => "U8",
StorageKind.GlobalMemoryU16 => "U16", StorageKind.GlobalMemoryU16 => "U16",
_ => string.Empty _ => string.Empty,
}; };
if (isMultiTarget) if (isMultiTarget)
@ -871,7 +870,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
StorageKind.GlobalMemoryU8 => 8, StorageKind.GlobalMemoryU8 => 8,
StorageKind.GlobalMemoryS16 or StorageKind.GlobalMemoryS16 or
StorageKind.GlobalMemoryU16 => 16, StorageKind.GlobalMemoryU16 => 16,
_ => 32 _ => 32,
}; };
if (bitSize < 32) if (bitSize < 32)

View file

@ -60,7 +60,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
bool isUnused = IsUnused(node.Value); bool isUnused = IsUnused(node.Value);
if (!(node.Value is Operation operation) || isUnused) if (node.Value is not Operation operation || isUnused)
{ {
if (node.Value is PhiNode phi && !isUnused) if (node.Value is PhiNode phi && !isUnused)
{ {
@ -199,7 +199,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
foreach (INode useNode in uses) foreach (INode useNode in uses)
{ {
if (!(useNode is Operation operation) || operation.Inst != Instruction.UnpackHalf2x16) if (useNode is not Operation operation || operation.Inst != Instruction.UnpackHalf2x16)
{ {
continue; continue;
} }
@ -248,12 +248,12 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
foreach (INode use in uses) foreach (INode use in uses)
{ {
if (!(use is Operation test)) if (use is not Operation test)
{ {
continue; continue;
} }
if (!(use is Operation useOp) || useOp.Inst != Instruction.SwizzleAdd) if (use is not Operation useOp || useOp.Inst != Instruction.SwizzleAdd)
{ {
continue; continue;
} }
@ -323,7 +323,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
Operand rhs = operation.GetSource(1); Operand rhs = operation.GetSource(1);
// Check LHS of the the main multiplication operation. We expect an input being multiplied by gl_FragCoord.w. // Check LHS of the the main multiplication operation. We expect an input being multiplied by gl_FragCoord.w.
if (!(lhs.AsgOp is Operation attrMulOp) || attrMulOp.Inst != (Instruction.FP32 | Instruction.Multiply)) if (lhs.AsgOp is not Operation attrMulOp || attrMulOp.Inst != (Instruction.FP32 | Instruction.Multiply))
{ {
return; return;
} }
@ -338,7 +338,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
} }
// RHS of the main multiplication should be a reciprocal operation (1.0 / x). // RHS of the main multiplication should be a reciprocal operation (1.0 / x).
if (!(rhs.AsgOp is Operation reciprocalOp) || reciprocalOp.Inst != (Instruction.FP32 | Instruction.Divide)) if (rhs.AsgOp is not Operation reciprocalOp || reciprocalOp.Inst != (Instruction.FP32 | Instruction.Divide))
{ {
return; return;
} }
@ -368,7 +368,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
// from all the use lists on the operands that this node uses. // from all the use lists on the operands that this node uses.
block.Operations.Remove(llNode); block.Operations.Remove(llNode);
Queue<INode> nodes = new Queue<INode>(); Queue<INode> nodes = new();
nodes.Enqueue(llNode.Value); nodes.Enqueue(llNode.Value);

View file

@ -14,7 +14,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
public static bool IsInputLoad(INode node, IoVariable ioVariable, int elemIndex) public static bool IsInputLoad(INode node, IoVariable ioVariable, int elemIndex)
{ {
if (!(node is Operation operation) || if (node is not Operation operation ||
operation.Inst != Instruction.Load || operation.Inst != Instruction.Load ||
operation.StorageKind != StorageKind.Input || operation.StorageKind != StorageKind.Input ||
operation.SourcesCount != 2) operation.SourcesCount != 2)

View file

@ -36,7 +36,7 @@ namespace Ryujinx.Graphics.Shader.Translation
FlagMask = flagMask; FlagMask = flagMask;
} }
public long GetMask(int index) public readonly long GetMask(int index)
{ {
return index switch return index switch
{ {
@ -46,7 +46,7 @@ namespace Ryujinx.Graphics.Shader.Translation
3 => GprMask3, 3 => GprMask3,
4 => PredMask, 4 => PredMask,
5 => FlagMask, 5 => FlagMask,
_ => throw new ArgumentOutOfRangeException(nameof(index)) _ => throw new ArgumentOutOfRangeException(nameof(index)),
}; };
} }
@ -93,12 +93,12 @@ namespace Ryujinx.Graphics.Shader.Translation
return !x.Equals(y); return !x.Equals(y);
} }
public override bool Equals(object obj) public readonly override bool Equals(object obj)
{ {
return obj is RegisterMask regMask && Equals(regMask); return obj is RegisterMask regMask && Equals(regMask);
} }
public bool Equals(RegisterMask other) public readonly bool Equals(RegisterMask other)
{ {
return GprMask0 == other.GprMask0 && return GprMask0 == other.GprMask0 &&
GprMask1 == other.GprMask1 && GprMask1 == other.GprMask1 &&
@ -108,7 +108,7 @@ namespace Ryujinx.Graphics.Shader.Translation
FlagMask == other.FlagMask; FlagMask == other.FlagMask;
} }
public override int GetHashCode() public readonly override int GetHashCode()
{ {
return HashCode.Combine(GprMask0, GprMask1, GprMask2, GprMask3, PredMask, FlagMask); return HashCode.Combine(GprMask0, GprMask1, GprMask2, GprMask3, PredMask, FlagMask);
} }
@ -128,8 +128,8 @@ namespace Ryujinx.Graphics.Shader.Translation
public static FunctionRegisterUsage RunPass(ControlFlowGraph cfg) public static FunctionRegisterUsage RunPass(ControlFlowGraph cfg)
{ {
List<Register> inArguments = new List<Register>(); List<Register> inArguments = new();
List<Register> outArguments = new List<Register>(); List<Register> outArguments = new();
// Compute local register inputs and outputs used inside blocks. // Compute local register inputs and outputs used inside blocks.
RegisterMask[] localInputs = new RegisterMask[cfg.Blocks.Length]; RegisterMask[] localInputs = new RegisterMask[cfg.Blocks.Length];
@ -168,8 +168,8 @@ namespace Ryujinx.Graphics.Shader.Translation
RegisterMask[] globalInputs = new RegisterMask[cfg.Blocks.Length]; RegisterMask[] globalInputs = new RegisterMask[cfg.Blocks.Length];
RegisterMask[] globalOutputs = new RegisterMask[cfg.Blocks.Length]; RegisterMask[] globalOutputs = new RegisterMask[cfg.Blocks.Length];
RegisterMask allOutputs = new RegisterMask(); RegisterMask allOutputs = new();
RegisterMask allCmnOutputs = new RegisterMask(-1L, -1L, -1L, -1L, -1L, -1L); RegisterMask allCmnOutputs = new(-1L, -1L, -1L, -1L, -1L, -1L);
bool modified; bool modified;
@ -389,14 +389,14 @@ namespace Ryujinx.Graphics.Shader.Translation
mask &= ~(1L << bit); mask &= ~(1L << bit);
Register register = new Register(baseRegIndex + bit, regType); Register register = new(baseRegIndex + bit, regType);
if (fillArgsList) if (fillArgsList)
{ {
inArguments.Add(register); inArguments.Add(register);
} }
Operation copyOp = new Operation(Instruction.Copy, OperandHelper.Register(register), OperandHelper.Argument(argIndex++)); Operation copyOp = new(Instruction.Copy, OperandHelper.Register(register), OperandHelper.Argument(argIndex++));
if (node == null) if (node == null)
{ {
@ -429,14 +429,14 @@ namespace Ryujinx.Graphics.Shader.Translation
mask &= ~(1L << bit); mask &= ~(1L << bit);
Register register = new Register(baseRegIndex + bit, regType); Register register = new(baseRegIndex + bit, regType);
if (fillArgsList) if (fillArgsList)
{ {
outArguments.Add(register); outArguments.Add(register);
} }
Operation copyOp = new Operation(Instruction.Copy, OperandHelper.Argument(argIndex++), OperandHelper.Register(register)); Operation copyOp = new(Instruction.Copy, OperandHelper.Argument(argIndex++), OperandHelper.Register(register));
if (node == null) if (node == null)
{ {
@ -475,7 +475,7 @@ namespace Ryujinx.Graphics.Shader.Translation
private static bool EndsWithReturn(BasicBlock block) private static bool EndsWithReturn(BasicBlock block)
{ {
if (!(block.GetLastOp() is Operation operation)) if (block.GetLastOp() is not Operation operation)
{ {
return false; return false;
} }

View file

@ -13,10 +13,9 @@ namespace Ryujinx.Graphics.Shader.Translation
private const int DefaultLocalMemorySize = 128; private const int DefaultLocalMemorySize = 128;
private const int DefaultSharedMemorySize = 4096; private const int DefaultSharedMemorySize = 4096;
private static readonly string[] _stagePrefixes = new string[] { "cp", "vp", "tcp", "tep", "gp", "fp" }; private static readonly string[] _stagePrefixes = { "cp", "vp", "tcp", "tep", "gp", "fp" };
private readonly IGpuAccessor _gpuAccessor; private readonly IGpuAccessor _gpuAccessor;
private readonly ShaderProperties _properties;
private readonly string _stagePrefix; private readonly string _stagePrefix;
private readonly int[] _cbSlotToBindingMap; private readonly int[] _cbSlotToBindingMap;
@ -31,12 +30,12 @@ namespace Ryujinx.Graphics.Shader.Translation
public int LocalMemoryId { get; private set; } public int LocalMemoryId { get; private set; }
public int SharedMemoryId { get; private set; } public int SharedMemoryId { get; private set; }
public ShaderProperties Properties => _properties; public ShaderProperties Properties { get; }
public ResourceManager(ShaderStage stage, IGpuAccessor gpuAccessor, ShaderProperties properties) public ResourceManager(ShaderStage stage, IGpuAccessor gpuAccessor, ShaderProperties properties)
{ {
_gpuAccessor = gpuAccessor; _gpuAccessor = gpuAccessor;
_properties = properties; Properties = properties;
_stagePrefix = GetShaderStagePrefix(stage); _stagePrefix = GetShaderStagePrefix(stage);
_cbSlotToBindingMap = new int[18]; _cbSlotToBindingMap = new int[18];
@ -211,7 +210,7 @@ namespace Ryujinx.Graphics.Shader.Translation
(int sbCbSlot, int sbCbOffset) = UnpackSbCbInfo(key); (int sbCbSlot, int sbCbOffset) = UnpackSbCbInfo(key);
descriptors[descriptorIndex++] = new BufferDescriptor(binding, slot, sbCbSlot, sbCbOffset) descriptors[descriptorIndex++] = new BufferDescriptor(binding, slot, sbCbSlot, sbCbOffset)
{ {
Flags = (_sbSlotWritten & (1u << slot)) != 0 ? BufferUsageFlags.Write : BufferUsageFlags.None Flags = (_sbSlotWritten & (1u << slot)) != 0 ? BufferUsageFlags.Write : BufferUsageFlags.None,
}; };
} }
} }
@ -226,39 +225,34 @@ namespace Ryujinx.Graphics.Shader.Translation
private void AddNewConstantBuffer(int binding, string name) private void AddNewConstantBuffer(int binding, string name)
{ {
StructureType type = new StructureType(new[] StructureType type = new(new[]
{ {
new StructureField(AggregateType.Array | AggregateType.Vector4 | AggregateType.FP32, "data", Constants.ConstantBufferSize / 16) new StructureField(AggregateType.Array | AggregateType.Vector4 | AggregateType.FP32, "data", Constants.ConstantBufferSize / 16),
}); });
_properties.AddConstantBuffer(binding, new BufferDefinition(BufferLayout.Std140, 0, binding, name, type)); Properties.AddConstantBuffer(binding, new BufferDefinition(BufferLayout.Std140, 0, binding, name, type));
} }
private void AddNewStorageBuffer(int binding, string name) private void AddNewStorageBuffer(int binding, string name)
{ {
StructureType type = new StructureType(new[] StructureType type = new(new[]
{ {
new StructureField(AggregateType.Array | AggregateType.U32, "data", 0) new StructureField(AggregateType.Array | AggregateType.U32, "data", 0),
}); });
_properties.AddStorageBuffer(binding, new BufferDefinition(BufferLayout.Std430, 1, binding, name, type)); Properties.AddStorageBuffer(binding, new BufferDefinition(BufferLayout.Std430, 1, binding, name, type));
} }
public static string GetShaderStagePrefix(ShaderStage stage) public static string GetShaderStagePrefix(ShaderStage stage)
{ {
uint index = (uint)stage; uint index = (uint)stage;
if (index >= _stagePrefixes.Length) return index >= _stagePrefixes.Length ? "invalid" : _stagePrefixes[index];
{
return "invalid";
}
return _stagePrefixes[index];
} }
private static int PackSbCbInfo(int sbCbSlot, int sbCbOffset) private static int PackSbCbInfo(int sbCbSlot, int sbCbOffset)
{ {
return sbCbOffset | ((int)sbCbSlot << 16); return sbCbOffset | (sbCbSlot << 16);
} }
private static (int, int) UnpackSbCbInfo(int key) private static (int, int) UnpackSbCbInfo(int key)

View file

@ -4,7 +4,6 @@ using Ryujinx.Graphics.Shader.Translation.Optimizations;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
namespace Ryujinx.Graphics.Shader.Translation namespace Ryujinx.Graphics.Shader.Translation
@ -134,7 +133,7 @@ namespace Ryujinx.Graphics.Shader.Translation
AggregateType.Vector2 => 2, AggregateType.Vector2 => 2,
AggregateType.Vector3 => 3, AggregateType.Vector3 => 3,
AggregateType.Vector4 => 4, AggregateType.Vector4 => 4,
_ => 1 _ => 1,
}; };
if (elemCount == 1) if (elemCount == 1)
@ -154,9 +153,9 @@ namespace Ryujinx.Graphics.Shader.Translation
inputs[srcIndex] = operation.GetSource(srcIndex); inputs[srcIndex] = operation.GetSource(srcIndex);
} }
inputs[inputs.Length - 1] = Const(i); inputs[^1] = Const(i);
Operation loadOp = new Operation(Instruction.Load, StorageKind.ConstantBuffer, value, inputs); Operation loadOp = new(Instruction.Load, StorageKind.ConstantBuffer, value, inputs);
node.List.AddBefore(node, loadOp); node.List.AddBefore(node, loadOp);
@ -169,8 +168,8 @@ namespace Ryujinx.Graphics.Shader.Translation
Operand isCurrentIndex = Local(); Operand isCurrentIndex = Local();
Operand selection = Local(); Operand selection = Local();
Operation compareOp = new Operation(Instruction.CompareEqual, isCurrentIndex, new Operand[] { elemIndex, Const(i) }); Operation compareOp = new(Instruction.CompareEqual, isCurrentIndex, new Operand[] { elemIndex, Const(i) });
Operation selectOp = new Operation(Instruction.ConditionalSelect, selection, new Operand[] { isCurrentIndex, value, result }); Operation selectOp = new(Instruction.ConditionalSelect, selection, new Operand[] { isCurrentIndex, value, result });
node.List.AddBefore(node, compareOp); node.List.AddBefore(node, compareOp);
node.List.AddBefore(node, selectOp); node.List.AddBefore(node, selectOp);
@ -269,8 +268,6 @@ namespace Ryujinx.Graphics.Shader.Translation
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0; bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
bool intCoords = (texOp.Flags & TextureFlags.IntCoords) != 0; bool intCoords = (texOp.Flags & TextureFlags.IntCoords) != 0;
bool isArray = (texOp.Type & SamplerType.Array) != 0;
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0; bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.GetDimensions();
@ -319,9 +316,6 @@ namespace Ryujinx.Graphics.Shader.Translation
TextureOperation texOp = (TextureOperation)node.Value; TextureOperation texOp = (TextureOperation)node.Value;
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0; bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
bool intCoords = (texOp.Flags & TextureFlags.IntCoords) != 0;
bool isArray = (texOp.Type & SamplerType.Array) != 0;
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0; bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
if (texOp.Inst == Instruction.TextureSize && if (texOp.Inst == Instruction.TextureSize &&
@ -393,7 +387,6 @@ namespace Ryujinx.Graphics.Shader.Translation
return node; return node;
} }
bool isArray = (texOp.Type & SamplerType.Array) != 0;
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0; bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.GetDimensions();
@ -462,10 +455,12 @@ namespace Ryujinx.Graphics.Shader.Translation
return node; return node;
} }
#pragma warning disable IDE0059 // Remove unnecessary value assignment
bool intCoords = (texOp.Flags & TextureFlags.IntCoords) != 0; bool intCoords = (texOp.Flags & TextureFlags.IntCoords) != 0;
bool isArray = (texOp.Type & SamplerType.Array) != 0; bool isArray = (texOp.Type & SamplerType.Array) != 0;
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0; bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
#pragma warning restore IDE0059
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.GetDimensions();
int coordsIndex = isBindless || isIndexed ? 1 : 0; int coordsIndex = isBindless || isIndexed ? 1 : 0;
@ -712,7 +707,7 @@ namespace Ryujinx.Graphics.Shader.Translation
newSources[coordsIndex + index] = coordPlusOffset; newSources[coordsIndex + index] = coordPlusOffset;
} }
TextureOperation newTexOp = new TextureOperation( TextureOperation newTexOp = new(
Instruction.TextureSample, Instruction.TextureSample,
texOp.Type, texOp.Type,
texOp.Format, texOp.Format,
@ -771,7 +766,7 @@ namespace Ryujinx.Graphics.Shader.Translation
} }
} }
TextureOperation newTexOp = new TextureOperation( TextureOperation newTexOp = new(
Instruction.TextureSample, Instruction.TextureSample,
texOp.Type, texOp.Type,
texOp.Format, texOp.Format,
@ -868,7 +863,7 @@ namespace Ryujinx.Graphics.Shader.Translation
TextureFormat.R16Snorm => short.MaxValue, TextureFormat.R16Snorm => short.MaxValue,
TextureFormat.R16G16Snorm => short.MaxValue, TextureFormat.R16G16Snorm => short.MaxValue,
TextureFormat.R16G16B16A16Snorm => short.MaxValue, TextureFormat.R16G16B16A16Snorm => short.MaxValue,
_ => 0 _ => 0,
}; };
// The value being 0 means that the format is not a SNORM format, // The value being 0 means that the format is not a SNORM format,
@ -886,8 +881,8 @@ namespace Ryujinx.Graphics.Shader.Translation
INode[] uses = dest.UseOps.ToArray(); INode[] uses = dest.UseOps.ToArray();
Operation convOp = new Operation(Instruction.ConvertS32ToFP32, Local(), dest); Operation convOp = new(Instruction.ConvertS32ToFP32, Local(), dest);
Operation normOp = new Operation(Instruction.FP32 | Instruction.Multiply, Local(), convOp.Dest, ConstF(1f / maxPositive)); Operation normOp = new(Instruction.FP32 | Instruction.Multiply, Local(), convOp.Dest, ConstF(1f / maxPositive));
node = node.List.AddAfter(node, convOp); node = node.List.AddAfter(node, convOp);
node = node.List.AddAfter(node, normOp); node = node.List.AddAfter(node, normOp);

View file

@ -148,25 +148,25 @@ namespace Ryujinx.Graphics.Shader.Translation
if (!gpuAccessor.QueryHostSupportsTransformFeedback() && gpuAccessor.QueryTransformFeedbackEnabled()) if (!gpuAccessor.QueryHostSupportsTransformFeedback() && gpuAccessor.QueryTransformFeedbackEnabled())
{ {
StructureType tfeInfoStruct = new StructureType(new StructureField[] StructureType tfeInfoStruct = new(new StructureField[]
{ {
new StructureField(AggregateType.Array | AggregateType.U32, "base_offset", 4), new(AggregateType.Array | AggregateType.U32, "base_offset", 4),
new StructureField(AggregateType.U32, "vertex_count") new(AggregateType.U32, "vertex_count"),
}); });
BufferDefinition tfeInfoBuffer = new BufferDefinition(BufferLayout.Std430, 1, Constants.TfeInfoBinding, "tfe_info", tfeInfoStruct); BufferDefinition tfeInfoBuffer = new(BufferLayout.Std430, 1, Constants.TfeInfoBinding, "tfe_info", tfeInfoStruct);
Properties.AddStorageBuffer(Constants.TfeInfoBinding, tfeInfoBuffer); Properties.AddStorageBuffer(Constants.TfeInfoBinding, tfeInfoBuffer);
StructureType tfeDataStruct = new StructureType(new StructureField[] StructureType tfeDataStruct = new(new StructureField[]
{ {
new StructureField(AggregateType.Array | AggregateType.U32, "data", 0) new(AggregateType.Array | AggregateType.U32, "data", 0),
}); });
for (int i = 0; i < Constants.TfeBuffersCount; i++) for (int i = 0; i < Constants.TfeBuffersCount; i++)
{ {
int binding = Constants.TfeBufferBaseBinding + i; int binding = Constants.TfeBufferBaseBinding + i;
BufferDefinition tfeDataBuffer = new BufferDefinition(BufferLayout.Std430, 1, binding, $"tfe_data{i}", tfeDataStruct); BufferDefinition tfeDataBuffer = new(BufferLayout.Std430, 1, binding, $"tfe_data{i}", tfeDataStruct);
Properties.AddStorageBuffer(binding, tfeDataBuffer); Properties.AddStorageBuffer(binding, tfeDataBuffer);
} }
} }
@ -524,7 +524,7 @@ namespace Ryujinx.Graphics.Shader.Translation
// Regular and per-patch input/output locations can't overlap, // Regular and per-patch input/output locations can't overlap,
// so we must assign on our location using unused regular input/output locations. // so we must assign on our location using unused regular input/output locations.
Dictionary<int, int> locationsMap = new Dictionary<int, int>(); Dictionary<int, int> locationsMap = new();
int freeMask = ~UsedOutputAttributes; int freeMask = ~UsedOutputAttributes;
@ -718,7 +718,7 @@ namespace Ryujinx.Graphics.Shader.Translation
{ {
AccurateType = accurateType, AccurateType = accurateType,
Type = type, Type = type,
UsageFlags = usageFlags UsageFlags = usageFlags,
}; };
if (dict.TryGetValue(info, out var existingMeta)) if (dict.TryGetValue(info, out var existingMeta))
@ -797,24 +797,6 @@ namespace Ryujinx.Graphics.Shader.Translation
return default; return default;
} }
private static int FindDescriptorIndex(TextureDescriptor[] array, AstTextureOperation texOp)
{
for (int i = 0; i < array.Length; i++)
{
var descriptor = array[i];
if (descriptor.Type == texOp.Type &&
descriptor.CbufSlot == texOp.CbufSlot &&
descriptor.HandleIndex == texOp.Handle &&
descriptor.Format == texOp.Format)
{
return i;
}
}
return -1;
}
private static int FindDescriptorIndex(TextureDescriptor[] array, TextureOperation texOp, bool ignoreType = false) private static int FindDescriptorIndex(TextureDescriptor[] array, TextureOperation texOp, bool ignoreType = false)
{ {
for (int i = 0; i < array.Length; i++) for (int i = 0; i < array.Length; i++)

View file

@ -9,7 +9,7 @@ namespace Ryujinx.Graphics.Shader.Translation
Unused = 0, Unused = 0,
Constant = 1, Constant = 1,
Perspective = 2, Perspective = 2,
ScreenLinear = 3 ScreenLinear = 3,
} }
readonly struct ImapPixelType readonly struct ImapPixelType
@ -29,9 +29,19 @@ namespace Ryujinx.Graphics.Shader.Translation
public PixelImap GetFirstUsedType() public PixelImap GetFirstUsedType()
{ {
if (X != PixelImap.Unused) return X; if (X != PixelImap.Unused)
if (Y != PixelImap.Unused) return Y; {
if (Z != PixelImap.Unused) return Z; return X;
}
if (Y != PixelImap.Unused)
{
return Y;
}
if (Z != PixelImap.Unused)
{
return Z;
}
return W; return W;
} }
} }

View file

@ -43,7 +43,7 @@ namespace Ryujinx.Graphics.Shader.Translation
foreach (INode node in block.Operations) foreach (INode node in block.Operations)
{ {
if (!(node is Operation operation)) if (node is not Operation operation)
{ {
continue; continue;
} }
@ -84,7 +84,7 @@ namespace Ryujinx.Graphics.Shader.Translation
} }
writesLayer = true; writesLayer = true;
layerInputAttr = srcAttributeAsgOp.GetSource(1).Value * 4 + srcAttributeAsgOp.GetSource(3).Value;; layerInputAttr = srcAttributeAsgOp.GetSource(1).Value * 4 + srcAttributeAsgOp.GetSource(3).Value;
} }
else else
{ {

View file

@ -1,7 +1,6 @@
using Ryujinx.Graphics.Shader.Decoders; using Ryujinx.Graphics.Shader.Decoders;
using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using System.Collections.Generic; using System.Collections.Generic;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
namespace Ryujinx.Graphics.Shader.Translation namespace Ryujinx.Graphics.Shader.Translation
@ -12,9 +11,9 @@ namespace Ryujinx.Graphics.Shader.Translation
private class DefMap private class DefMap
{ {
private Dictionary<Register, Operand> _map; private readonly Dictionary<Register, Operand> _map;
private long[] _phiMasks; private readonly long[] _phiMasks;
public DefMap() public DefMap()
{ {
@ -65,8 +64,8 @@ namespace Ryujinx.Graphics.Shader.Translation
private class LocalDefMap private class LocalDefMap
{ {
private Operand[] _map; private readonly Operand[] _map;
private int[] _uses; private readonly int[] _uses;
public int UseCount { get; private set; } public int UseCount { get; private set; }
public LocalDefMap() public LocalDefMap()
@ -123,14 +122,14 @@ namespace Ryujinx.Graphics.Shader.Translation
public static void Rename(BasicBlock[] blocks) public static void Rename(BasicBlock[] blocks)
{ {
DefMap[] globalDefs = new DefMap[blocks.Length]; DefMap[] globalDefs = new DefMap[blocks.Length];
LocalDefMap localDefs = new LocalDefMap(); LocalDefMap localDefs = new();
for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++) for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++)
{ {
globalDefs[blkIndex] = new DefMap(); globalDefs[blkIndex] = new DefMap();
} }
Queue<BasicBlock> dfPhiBlocks = new Queue<BasicBlock>(); Queue<BasicBlock> dfPhiBlocks = new();
// First pass, get all defs and locals uses. // First pass, get all defs and locals uses.
for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++) for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++)
@ -303,7 +302,7 @@ namespace Ryujinx.Graphics.Shader.Translation
// then use the definition from that Phi. // then use the definition from that Phi.
Operand local = Local(); Operand local = Local();
PhiNode phi = new PhiNode(local); PhiNode phi = new(local);
AddPhi(block, phi); AddPhi(block, phi);

View file

@ -3,6 +3,6 @@ namespace Ryujinx.Graphics.Shader.Translation
public enum TargetApi public enum TargetApi
{ {
OpenGL, OpenGL,
Vulkan Vulkan,
} }
} }

View file

@ -4,6 +4,6 @@ namespace Ryujinx.Graphics.Shader.Translation
{ {
Glsl, Glsl,
Spirv, Spirv,
Arb Arb,
} }
} }

Some files were not shown because too many files have changed in this diff Show more