BindlessToIndexed.cs 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. using Ryujinx.Graphics.Shader.IntermediateRepresentation;
  2. using System.Collections.Generic;
  3. using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
  4. namespace Ryujinx.Graphics.Shader.Translation.Optimizations
  5. {
  6. static class BindlessToIndexed
  7. {
  8. public static void RunPass(BasicBlock block, ShaderConfig config)
  9. {
  10. // We can turn a bindless texture access into a indexed access,
  11. // as long the following conditions are true:
  12. // - The handle is loaded using a LDC instruction.
  13. // - The handle is loaded from the constant buffer with the handles (CB2 for NVN).
  14. // - The load has a constant offset.
  15. // The base offset of the array of handles on the constant buffer is the constant offset.
  16. for (LinkedListNode<INode> node = block.Operations.First; node != null; node = node.Next)
  17. {
  18. if (!(node.Value is TextureOperation texOp))
  19. {
  20. continue;
  21. }
  22. if ((texOp.Flags & TextureFlags.Bindless) == 0)
  23. {
  24. continue;
  25. }
  26. if (!(texOp.GetSource(0).AsgOp is Operation handleAsgOp))
  27. {
  28. continue;
  29. }
  30. if (handleAsgOp.Inst != Instruction.LoadConstant)
  31. {
  32. continue;
  33. }
  34. Operand ldcSrc0 = handleAsgOp.GetSource(0);
  35. Operand ldcSrc1 = handleAsgOp.GetSource(1);
  36. if (ldcSrc0.Type != OperandType.Constant || ldcSrc0.Value != 2)
  37. {
  38. continue;
  39. }
  40. if (!(ldcSrc1.AsgOp is Operation shrOp) || shrOp.Inst != Instruction.ShiftRightU32)
  41. {
  42. continue;
  43. }
  44. if (!(shrOp.GetSource(0).AsgOp is Operation addOp) || addOp.Inst != Instruction.Add)
  45. {
  46. continue;
  47. }
  48. Operand addSrc1 = addOp.GetSource(1);
  49. if (addSrc1.Type != OperandType.Constant)
  50. {
  51. continue;
  52. }
  53. TurnIntoIndexed(config, texOp, addSrc1.Value / 4);
  54. Operand index = Local();
  55. Operand source = addOp.GetSource(0);
  56. Operation shrBy3 = new Operation(Instruction.ShiftRightU32, index, source, Const(3));
  57. block.Operations.AddBefore(node, shrBy3);
  58. texOp.SetSource(0, index);
  59. }
  60. }
  61. private static void TurnIntoIndexed(ShaderConfig config, TextureOperation texOp, int handle)
  62. {
  63. texOp.TurnIntoIndexed(handle);
  64. config.SetUsedTexture(texOp.Inst, texOp.Type, texOp.Format, texOp.Flags, texOp.CbufSlot, handle);
  65. }
  66. }
  67. }