texture_gather_swizzled.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. // Copyright 2021 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <utility>
  5. #include "common/bit_field.h"
  6. #include "common/common_types.h"
  7. #include "shader_recompiler/frontend/ir/modifiers.h"
  8. #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
  9. namespace Shader::Maxwell {
  10. namespace {
  11. enum class Precision : u64 {
  12. F32,
  13. F16,
  14. };
  15. enum class ComponentType : u64 {
  16. R = 0,
  17. G = 1,
  18. B = 2,
  19. A = 3,
  20. };
  21. union Encoding {
  22. u64 raw;
  23. BitField<55, 1, Precision> precision;
  24. BitField<52, 2, ComponentType> component_type;
  25. BitField<51, 1, u64> aoffi;
  26. BitField<50, 1, u64> dc;
  27. BitField<49, 1, u64> nodep;
  28. BitField<28, 8, IR::Reg> dest_reg_b;
  29. BitField<0, 8, IR::Reg> dest_reg_a;
  30. BitField<8, 8, IR::Reg> src_reg_a;
  31. BitField<20, 8, IR::Reg> src_reg_b;
  32. BitField<36, 13, u64> cbuf_offset;
  33. };
  34. void CheckAlignment(IR::Reg reg, size_t alignment) {
  35. if (!IR::IsAligned(reg, alignment)) {
  36. throw NotImplementedException("Unaligned source register {}", reg);
  37. }
  38. }
  39. IR::Value MakeOffset(TranslatorVisitor& v, IR::Reg reg) {
  40. const IR::U32 value{v.X(reg)};
  41. return v.ir.CompositeConstruct(v.ir.BitFieldExtract(value, v.ir.Imm32(0), v.ir.Imm32(6), true),
  42. v.ir.BitFieldExtract(value, v.ir.Imm32(8), v.ir.Imm32(6), true));
  43. }
  44. IR::Value Sample(TranslatorVisitor& v, u64 insn) {
  45. const Encoding tld4s{insn};
  46. const IR::U32 handle{v.ir.Imm32(static_cast<u32>(tld4s.cbuf_offset * 4))};
  47. const IR::Reg reg_a{tld4s.src_reg_a};
  48. const IR::Reg reg_b{tld4s.src_reg_b};
  49. IR::TextureInstInfo info{};
  50. if (tld4s.precision == Precision::F16) {
  51. info.relaxed_precision.Assign(1);
  52. }
  53. info.gather_component.Assign(static_cast<u32>(tld4s.component_type.Value()));
  54. info.type.Assign(tld4s.dc != 0 ? Shader::TextureType::Shadow2D : Shader::TextureType::Color2D);
  55. IR::Value coords;
  56. if (tld4s.aoffi != 0) {
  57. CheckAlignment(reg_a, 2);
  58. coords = v.ir.CompositeConstruct(v.F(reg_a), v.F(reg_a + 1));
  59. IR::Value offset = MakeOffset(v, reg_b);
  60. if (tld4s.dc != 0) {
  61. CheckAlignment(reg_b, 2);
  62. IR::F32 dref = v.F(reg_b + 1);
  63. return v.ir.ImageGatherDref(handle, coords, offset, {}, dref, info);
  64. }
  65. return v.ir.ImageGather(handle, coords, offset, {}, info);
  66. }
  67. if (tld4s.dc != 0) {
  68. CheckAlignment(reg_a, 2);
  69. coords = v.ir.CompositeConstruct(v.F(reg_a), v.F(reg_a + 1));
  70. IR::F32 dref = v.F(reg_b);
  71. return v.ir.ImageGatherDref(handle, coords, {}, {}, dref, info);
  72. }
  73. coords = v.ir.CompositeConstruct(v.F(reg_a), v.F(reg_b));
  74. return v.ir.ImageGather(handle, coords, {}, {}, info);
  75. }
  76. IR::Reg RegStoreComponent32(u64 insn, size_t index) {
  77. const Encoding tlds4{insn};
  78. switch (index) {
  79. case 0:
  80. return tlds4.dest_reg_a;
  81. case 1:
  82. CheckAlignment(tlds4.dest_reg_a, 2);
  83. return tlds4.dest_reg_a + 1;
  84. case 2:
  85. return tlds4.dest_reg_b;
  86. case 3:
  87. CheckAlignment(tlds4.dest_reg_b, 2);
  88. return tlds4.dest_reg_b + 1;
  89. }
  90. throw LogicError("Invalid store index {}", index);
  91. }
  92. void Store32(TranslatorVisitor& v, u64 insn, const IR::Value& sample) {
  93. for (size_t component = 0; component < 4; ++component) {
  94. const IR::Reg dest{RegStoreComponent32(insn, component)};
  95. v.F(dest, IR::F32{v.ir.CompositeExtract(sample, component)});
  96. }
  97. }
  98. IR::U32 Pack(TranslatorVisitor& v, const IR::F32& lhs, const IR::F32& rhs) {
  99. return v.ir.PackHalf2x16(v.ir.CompositeConstruct(lhs, rhs));
  100. }
  101. void Store16(TranslatorVisitor& v, u64 insn, const IR::Value& sample) {
  102. std::array<IR::F32, 4> swizzled;
  103. for (size_t component = 0; component < 4; ++component) {
  104. swizzled[component] = IR::F32{v.ir.CompositeExtract(sample, component)};
  105. }
  106. const Encoding tld4s{insn};
  107. v.X(tld4s.dest_reg_a, Pack(v, swizzled[0], swizzled[1]));
  108. v.X(tld4s.dest_reg_b, Pack(v, swizzled[2], swizzled[3]));
  109. }
  110. } // Anonymous namespace
  111. void TranslatorVisitor::TLD4S(u64 insn) {
  112. const IR::Value sample{Sample(*this, insn)};
  113. if (Encoding{insn}.precision == Precision::F32) {
  114. Store32(*this, insn, sample);
  115. } else {
  116. Store16(*this, insn, sample);
  117. }
  118. }
  119. } // namespace Shader::Maxwell