texture_gather_swizzled.cpp 4.2 KB

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