From 1ab42e9ce8dd1e288c02bd94d9642840988acf3c Mon Sep 17 00:00:00 2001 From: gdk Date: Sat, 19 Feb 2022 20:25:39 -0300 Subject: [PATCH] SPIR-V: Implement SwizzleAdd, add missing Triangles ExecutionMode for geometry shaders, remove SamplerType field from TextureMeta --- .../CodeGen/Spirv/Declarations.cs | 22 +++++----- .../CodeGen/Spirv/Instructions.cs | 41 ++++++++++++++++--- .../CodeGen/Spirv/SpirvGenerator.cs | 3 ++ .../CodeGen/Spirv/TextureMeta.cs | 8 ++-- 4 files changed, 52 insertions(+), 22 deletions(-) diff --git a/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs b/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs index 50ed91eef..f23444389 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs @@ -177,7 +177,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv { foreach (var descriptor in descriptors) { - var meta = new TextureMeta(descriptor.CbufSlot, descriptor.HandleIndex, descriptor.Format, descriptor.Type); + var meta = new TextureMeta(descriptor.CbufSlot, descriptor.HandleIndex, descriptor.Format); if (context.Samplers.ContainsKey(meta)) { @@ -187,22 +187,22 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv bool isBuffer = (descriptor.Type & SamplerType.Mask) == SamplerType.TextureBuffer; int setIndex = context.Config.Options.TargetApi == TargetApi.Vulkan ? (isBuffer ? 4 : 2) : 0; - var dim = (meta.Type & SamplerType.Mask) switch + var dim = (descriptor.Type & SamplerType.Mask) switch { SamplerType.Texture1D => Dim.Dim1D, SamplerType.Texture2D => Dim.Dim2D, SamplerType.Texture3D => Dim.Dim3D, SamplerType.TextureCube => Dim.Cube, SamplerType.TextureBuffer => Dim.Buffer, - _ => throw new InvalidOperationException($"Invalid sampler type \"{meta.Type & SamplerType.Mask}\".") + _ => throw new InvalidOperationException($"Invalid sampler type \"{descriptor.Type & SamplerType.Mask}\".") }; var imageType = context.TypeImage( context.TypeFP32(), dim, - meta.Type.HasFlag(SamplerType.Shadow), - meta.Type.HasFlag(SamplerType.Array), - meta.Type.HasFlag(SamplerType.Multisample), + descriptor.Type.HasFlag(SamplerType.Shadow), + descriptor.Type.HasFlag(SamplerType.Array), + descriptor.Type.HasFlag(SamplerType.Multisample), 1, ImageFormat.Unknown); @@ -225,7 +225,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv { foreach (var descriptor in descriptors) { - var meta = new TextureMeta(descriptor.CbufSlot, descriptor.HandleIndex, descriptor.Format, descriptor.Type); + var meta = new TextureMeta(descriptor.CbufSlot, descriptor.HandleIndex, descriptor.Format); if (context.Images.ContainsKey(meta)) { @@ -235,14 +235,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv bool isBuffer = (descriptor.Type & SamplerType.Mask) == SamplerType.TextureBuffer; int setIndex = context.Config.Options.TargetApi == TargetApi.Vulkan ? (isBuffer ? 5 : 3) : 0; - var dim = GetDim(meta.Type); + var dim = GetDim(descriptor.Type); var imageType = context.TypeImage( context.GetType(meta.Format.GetComponentType().Convert()), dim, - meta.Type.HasFlag(SamplerType.Shadow), - meta.Type.HasFlag(SamplerType.Array), - meta.Type.HasFlag(SamplerType.Multisample), + descriptor.Type.HasFlag(SamplerType.Shadow), + descriptor.Type.HasFlag(SamplerType.Array), + descriptor.Type.HasFlag(SamplerType.Multisample), AccessQualifier.ReadWrite, GetImageFormat(meta.Format)); diff --git a/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs b/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs index 54ad3c96d..90a55f626 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs @@ -125,6 +125,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv Add(Instruction.StoreShared, GenerateStoreShared); Add(Instruction.StoreStorage, GenerateStoreStorage); Add(Instruction.Subtract, GenerateSubtract); + Add(Instruction.SwizzleAdd, GenerateSwizzleAdd); Add(Instruction.TextureSample, GenerateTextureSample); Add(Instruction.TextureSize, GenerateTextureSize); Add(Instruction.Truncate, GenerateTruncate); @@ -638,7 +639,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv SpvInstruction value = Src(componentType.Convert()); - (var imageType, var imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format, texOp.Type)]; + (var imageType, var imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)]; var image = context.Load(imageType, imageVariable); @@ -732,7 +733,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv pCoords = Src(AggregateType.S32); } - (var imageType, var imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format, texOp.Type)]; + (var imageType, var imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)]; var image = context.Load(imageType, imageVariable); @@ -819,7 +820,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv var texel = context.CompositeConstruct(context.TypeVector(context.GetType(componentType.Convert()), ComponentsCount), cElems); - (var imageType, var imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format, texOp.Type)]; + (var imageType, var imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)]; var image = context.Load(imageType, imageVariable); @@ -968,7 +969,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv pCoords = Src(AggregateType.FP32); } - var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format, texOp.Type); + var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format); (_, var sampledImageType, var sampledImageVariable) = context.Samplers[meta]; @@ -1281,6 +1282,34 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv return GenerateBinary(context, operation, context.Delegates.FSub, context.Delegates.ISub); } + private static OperationResult GenerateSwizzleAdd(CodeGenContext context, AstOperation operation) + { + var x = context.Get(AggregateType.FP32, operation.GetSource(0)); + var y = context.Get(AggregateType.FP32, operation.GetSource(1)); + var mask = context.Get(AggregateType.U32, operation.GetSource(2)); + + var v4float = context.TypeVector(context.TypeFP32(), (SpvLiteralInteger)4); + var one = context.Constant(context.TypeFP32(), (SpvLiteralInteger)1.0f); + var minusOne = context.Constant(context.TypeFP32(), (SpvLiteralInteger)(-1.0f)); + var zero = context.Constant(context.TypeFP32(), (SpvLiteralInteger)0.0f); + var xLut = context.ConstantComposite(v4float, one, minusOne, one, zero); + var yLut = context.ConstantComposite(v4float, one, one, minusOne, one); + + var threadId = context.GetAttribute(AggregateType.U32, AttributeConsts.LaneId, false); + var shift = context.BitwiseAnd(context.TypeU32(), threadId, context.Constant(context.TypeU32(), (SpvLiteralInteger)3)); + shift = context.ShiftLeftLogical(context.TypeU32(), shift, context.Constant(context.TypeU32(), (SpvLiteralInteger)1)); + var lutIdx = context.ShiftRightLogical(context.TypeU32(), mask, shift); + + var xLutValue = context.AccessChain(context.TypeFP32(), xLut, lutIdx); + var yLutValue = context.AccessChain(context.TypeFP32(), yLut, lutIdx); + + var xResult = context.FMul(context.TypeFP32(), x, xLutValue); + var yResult = context.FMul(context.TypeFP32(), y, yLutValue); + var result = context.FAdd(context.TypeFP32(), xResult, yResult); + + return new OperationResult(AggregateType.FP32, result); + } + private static OperationResult GenerateTextureSample(CodeGenContext context, AstOperation operation) { AstTextureOperation texOp = (AstTextureOperation)operation; @@ -1520,7 +1549,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv bool colorIsVector = isGather || !isShadow; var resultType = colorIsVector ? context.TypeVector(context.TypeFP32(), 4) : context.TypeFP32(); - var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format, texOp.Type); + var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format); (var imageType, var sampledImageType, var sampledImageVariable) = context.Samplers[meta]; @@ -1603,7 +1632,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv var lod = context.GetS32(operation.GetSource(lodSrcIndex)); - var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format, texOp.Type); + var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format); (var imageType, var sampledImageType, var sampledImageVariable) = context.Samplers[meta]; diff --git a/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs b/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs index 2e03f7375..37b6be7f5 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs @@ -163,6 +163,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv case InputTopology.LinesAdjacency: context.AddExecutionMode(spvFunc, ExecutionMode.InputLinesAdjacency); break; + case InputTopology.Triangles: + context.AddExecutionMode(spvFunc, ExecutionMode.Triangles); + break; case InputTopology.TrianglesAdjacency: context.AddExecutionMode(spvFunc, ExecutionMode.InputTrianglesAdjacency); break; diff --git a/Ryujinx.Graphics.Shader/CodeGen/Spirv/TextureMeta.cs b/Ryujinx.Graphics.Shader/CodeGen/Spirv/TextureMeta.cs index 9c684d858..686259ad7 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Spirv/TextureMeta.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Spirv/TextureMeta.cs @@ -7,14 +7,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv public int CbufSlot { get; } public int Handle { get; } public TextureFormat Format { get; } - public SamplerType Type { get; } - public TextureMeta(int cbufSlot, int handle, TextureFormat format, SamplerType type) + public TextureMeta(int cbufSlot, int handle, TextureFormat format) { CbufSlot = cbufSlot; Handle = handle; Format = format; - Type = type; } public override bool Equals(object obj) @@ -24,12 +22,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv public bool Equals(TextureMeta other) { - return CbufSlot == other.CbufSlot && Handle == other.Handle && Format == other.Format && Type == other.Type; + return CbufSlot == other.CbufSlot && Handle == other.Handle && Format == other.Format; } public override int GetHashCode() { - return HashCode.Combine(CbufSlot, Handle, Format, Type); + return HashCode.Combine(CbufSlot, Handle, Format); } } } \ No newline at end of file