diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2021-10-18 18:38:04 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-10-18 18:38:04 -0300 |
| commit | d512ce122cb1c9a7fe7cb40d3f85d642ee37f897 (patch) | |
| tree | bd20273250bf8066fa4df4b67c0de2ab9eac8092 /Ryujinx.Graphics.Shader/Instructions | |
| parent | 7603dbe3c8b45c8563f320f17ce784151cb1f0a8 (diff) | |
Initial tessellation shader support (#2534)
* Initial tessellation shader support
* Nits
* Re-arrange built-in table
* This is not needed anymore
* PR feedback
Diffstat (limited to 'Ryujinx.Graphics.Shader/Instructions')
4 files changed, 107 insertions, 14 deletions
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs index 9cc591ca..33c1065a 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs @@ -474,13 +474,6 @@ namespace Ryujinx.Graphics.Shader.Instructions context.Config.GpuAccessor.Log("Shader instruction Vset is not implemented."); } - public static void Vsetp(EmitterContext context) - { - InstVsetp op = context.GetOp<InstVsetp>(); - - context.Config.GpuAccessor.Log("Shader instruction Vsetp is not implemented."); - } - public static void Vshl(EmitterContext context) { InstVshl op = context.GetOp<InstVshl>(); diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitAttribute.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitAttribute.cs index e865caf2..f82b835c 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitAttribute.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitAttribute.cs @@ -40,19 +40,33 @@ namespace Ryujinx.Graphics.Shader.Instructions context.Config.SetUsedFeature(FeatureFlags.IaIndexing); } - else if (op.SrcB == RegisterConsts.RegisterZeroIndex) + else if (op.SrcB == RegisterConsts.RegisterZeroIndex || op.P) { - Operand src = Attribute(op.Imm11 + index * 4); + int offset = op.Imm11 + index * 4; - context.FlagAttributeRead(src.Value); + context.FlagAttributeRead(offset); + + if (op.O) + { + offset |= AttributeConsts.LoadOutputMask; + } + + Operand src = op.P ? AttributePerPatch(offset) : Attribute(offset); context.Copy(Register(rd), src); } else { - Operand src = Const(op.Imm11 + index * 4); + int offset = op.Imm11 + index * 4; + + context.FlagAttributeRead(offset); - context.FlagAttributeRead(src.Value); + if (op.O) + { + offset |= AttributeConsts.LoadOutputMask; + } + + Operand src = Const(offset); context.Copy(Register(rd), context.LoadAttribute(src, Const(0), primVertex)); } @@ -83,9 +97,13 @@ namespace Ryujinx.Graphics.Shader.Instructions } else { - Operand dest = Attribute(op.Imm11 + index * 4); + // TODO: Support indirect stores using Ra. + + int offset = op.Imm11 + index * 4; + + context.FlagAttributeWritten(offset); - context.FlagAttributeWritten(dest.Value); + Operand dest = op.P ? AttributePerPatch(offset) : Attribute(offset); context.Copy(dest, Register(rd)); } diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs index 245b2253..240fd6b1 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs @@ -79,6 +79,10 @@ namespace Ryujinx.Graphics.Shader.Instructions src = Attribute(AttributeConsts.LaneId); break; + case SReg.InvocationId: + src = Attribute(AttributeConsts.InvocationId); + break; + case SReg.YDirection: src = ConstF(1); // TODO: Use value from Y direction GPU register. break; @@ -87,6 +91,22 @@ namespace Ryujinx.Graphics.Shader.Instructions src = context.Config.Stage == ShaderStage.Fragment ? Attribute(AttributeConsts.ThreadKill) : Const(0); break; + case SReg.InvocationInfo: + if (context.Config.Stage != ShaderStage.Compute && context.Config.Stage != ShaderStage.Fragment) + { + Operand primitiveId = Attribute(AttributeConsts.PrimitiveId); + Operand patchVerticesIn = Attribute(AttributeConsts.PatchVerticesIn); + + patchVerticesIn = context.ShiftLeft(patchVerticesIn, Const(16)); + + src = context.BitwiseOr(primitiveId, patchVerticesIn); + } + else + { + src = Const(0); + } + break; + case SReg.TId: Operand tidX = Attribute(AttributeConsts.ThreadIdX); Operand tidY = Attribute(AttributeConsts.ThreadIdY); diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitVideoMinMax.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitVideoMinMax.cs index 890b31d6..120d6f22 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitVideoMinMax.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitVideoMinMax.cs @@ -120,6 +120,68 @@ namespace Ryujinx.Graphics.Shader.Instructions context.Copy(GetDest(op.Dest), res); } + public static void Vsetp(EmitterContext context) + { + InstVsetp op = context.GetOp<InstVsetp>(); + + Operand srcA = Extend(context, GetSrcReg(context, op.SrcA), op.ASelect); + + Operand srcB; + + if (op.BVideo) + { + srcB = Extend(context, GetSrcReg(context, op.SrcB), op.BSelect); + } + else + { + int imm = op.Imm16; + + if ((op.BSelect & VectorSelect.S8B0) != 0) + { + imm = (imm << 16) >> 16; + } + + srcB = Const(imm); + } + + Operand p0Res; + + bool signedA = (op.ASelect & VectorSelect.S8B0) != 0; + bool signedB = (op.BSelect & VectorSelect.S8B0) != 0; + + if (signedA != signedB) + { + bool a32 = (op.ASelect & ~VectorSelect.S8B0) == VectorSelect.U32; + bool b32 = (op.BSelect & ~VectorSelect.S8B0) == VectorSelect.U32; + + if (!a32 && !b32) + { + // Both values are extended small integer and can always fit in a S32, just do a signed comparison. + p0Res = GetIntComparison(context, op.VComp, srcA, srcB, isSigned: true, extended: false); + } + else + { + // TODO: Mismatching sign case. + p0Res = Const(0); + } + } + else + { + // Sign matches, just do a regular comparison. + p0Res = GetIntComparison(context, op.VComp, srcA, srcB, signedA, extended: false); + } + + Operand p1Res = context.BitwiseNot(p0Res); + + Operand pred = GetPredicate(context, op.SrcPred, op.SrcPredInv); + + p0Res = InstEmitAluHelper.GetPredLogicalOp(context, op.BoolOp, p0Res, pred); + p1Res = InstEmitAluHelper.GetPredLogicalOp(context, op.BoolOp, p1Res, pred); + + context.Copy(Register(op.DestPred, RegisterType.Predicate), p0Res); + context.Copy(Register(op.DestPredInv, RegisterType.Predicate), p1Res); + } + private static Operand Extend(EmitterContext context, Operand src, VectorSelect type) { return type switch |
