InstEmitVideo.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. using Ryujinx.Graphics.Shader.Decoders;
  2. using Ryujinx.Graphics.Shader.IntermediateRepresentation;
  3. using Ryujinx.Graphics.Shader.Translation;
  4. using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
  5. using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
  6. namespace Ryujinx.Graphics.Shader.Instructions
  7. {
  8. static partial class InstEmit
  9. {
  10. public static void Vmad(EmitterContext context)
  11. {
  12. // TODO: Implement properly.
  13. context.Copy(GetDest(context), GetSrcC(context));
  14. }
  15. public static void Vmnmx(EmitterContext context)
  16. {
  17. OpCodeVideo op = (OpCodeVideo)context.CurrOp;
  18. bool max = op.RawOpCode.Extract(56);
  19. Operand srcA = Extend(context, GetSrcA(context), op.RaSelection, op.RaType);
  20. Operand srcC = GetSrcC(context);
  21. Operand srcB;
  22. if (op.HasRb)
  23. {
  24. srcB = Extend(context, Register(op.Rb), op.RbSelection, op.RbType);
  25. }
  26. else
  27. {
  28. srcB = Const(op.Immediate);
  29. }
  30. Operand res;
  31. bool resSigned;
  32. if ((op.RaType & VideoType.Signed) != (op.RbType & VideoType.Signed))
  33. {
  34. // Signedness is different, but for max, result will always fit a U32,
  35. // since one of the inputs can't be negative, and the result is the one
  36. // with highest value. For min, it will always fit on a S32, since
  37. // one of the input can't be greater than INT_MAX and we want the lowest value.
  38. resSigned = !max;
  39. res = max ? context.IMaximumU32(srcA, srcB) : context.IMinimumS32(srcA, srcB);
  40. if ((op.RaType & VideoType.Signed) != 0)
  41. {
  42. Operand isBGtIntMax = context.ICompareLess(srcB, Const(0));
  43. res = context.ConditionalSelect(isBGtIntMax, srcB, res);
  44. }
  45. else
  46. {
  47. Operand isAGtIntMax = context.ICompareLess(srcA, Const(0));
  48. res = context.ConditionalSelect(isAGtIntMax, srcA, res);
  49. }
  50. }
  51. else
  52. {
  53. // Ra and Rb have the same signedness, so doesn't matter which one we test.
  54. resSigned = (op.RaType & VideoType.Signed) != 0;
  55. if (max)
  56. {
  57. res = resSigned
  58. ? context.IMaximumS32(srcA, srcB)
  59. : context.IMaximumU32(srcA, srcB);
  60. }
  61. else
  62. {
  63. res = resSigned
  64. ? context.IMinimumS32(srcA, srcB)
  65. : context.IMinimumU32(srcA, srcB);
  66. }
  67. }
  68. if (op.Saturate)
  69. {
  70. if (op.DstSigned && !resSigned)
  71. {
  72. res = context.IMinimumU32(res, Const(int.MaxValue));
  73. }
  74. else if (!op.DstSigned && resSigned)
  75. {
  76. res = context.IMaximumS32(res, Const(0));
  77. }
  78. }
  79. switch (op.PostOp)
  80. {
  81. case VideoPostOp.Acc:
  82. res = context.IAdd(res, srcC);
  83. break;
  84. case VideoPostOp.Max:
  85. res = op.DstSigned ? context.IMaximumS32(res, srcC) : context.IMaximumU32(res, srcC);
  86. break;
  87. case VideoPostOp.Min:
  88. res = op.DstSigned ? context.IMinimumS32(res, srcC) : context.IMinimumU32(res, srcC);
  89. break;
  90. case VideoPostOp.Mrg16h:
  91. res = context.BitfieldInsert(srcC, res, Const(16), Const(16));
  92. break;
  93. case VideoPostOp.Mrg16l:
  94. res = context.BitfieldInsert(srcC, res, Const(0), Const(16));
  95. break;
  96. case VideoPostOp.Mrg8b0:
  97. res = context.BitfieldInsert(srcC, res, Const(0), Const(8));
  98. break;
  99. case VideoPostOp.Mrg8b2:
  100. res = context.BitfieldInsert(srcC, res, Const(16), Const(8));
  101. break;
  102. }
  103. context.Copy(GetDest(context), res);
  104. }
  105. private static Operand Extend(EmitterContext context, Operand src, int sel, VideoType type)
  106. {
  107. return type switch
  108. {
  109. VideoType.U8 => ZeroExtendTo32(context, context.ShiftRightU32(src, Const(sel * 8)), 8),
  110. VideoType.U16 => ZeroExtendTo32(context, context.ShiftRightU32(src, Const(sel * 16)), 16),
  111. VideoType.S8 => SignExtendTo32(context, context.ShiftRightU32(src, Const(sel * 8)), 8),
  112. VideoType.S16 => SignExtendTo32(context, context.ShiftRightU32(src, Const(sel * 16)), 16),
  113. _ => src
  114. };
  115. }
  116. }
  117. }