macro_hle.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include <array>
  4. #include <vector>
  5. #include "video_core/engines/maxwell_3d.h"
  6. #include "video_core/macro/macro.h"
  7. #include "video_core/macro/macro_hle.h"
  8. #include "video_core/rasterizer_interface.h"
  9. namespace Tegra {
  10. namespace {
  11. using HLEFunction = void (*)(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters);
  12. // HLE'd functions
  13. void HLE_771BB18C62444DA0(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) {
  14. const u32 instance_count = parameters[2] & maxwell3d.GetRegisterValue(0xD1B);
  15. maxwell3d.regs.draw.topology.Assign(
  16. static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0] & 0x3ffffff));
  17. maxwell3d.regs.vb_base_instance = parameters[5];
  18. maxwell3d.mme_draw.instance_count = instance_count;
  19. maxwell3d.regs.vb_element_base = parameters[3];
  20. maxwell3d.regs.index_array.count = parameters[1];
  21. maxwell3d.regs.index_array.first = parameters[4];
  22. if (maxwell3d.ShouldExecute()) {
  23. maxwell3d.Rasterizer().Draw(true, true);
  24. }
  25. maxwell3d.regs.index_array.count = 0;
  26. maxwell3d.mme_draw.instance_count = 0;
  27. maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined;
  28. }
  29. void HLE_0D61FC9FAAC9FCAD(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) {
  30. const u32 count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]);
  31. maxwell3d.regs.vertex_buffer.first = parameters[3];
  32. maxwell3d.regs.vertex_buffer.count = parameters[1];
  33. maxwell3d.regs.vb_base_instance = parameters[4];
  34. maxwell3d.regs.draw.topology.Assign(
  35. static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0]));
  36. maxwell3d.mme_draw.instance_count = count;
  37. if (maxwell3d.ShouldExecute()) {
  38. maxwell3d.Rasterizer().Draw(false, true);
  39. }
  40. maxwell3d.regs.vertex_buffer.count = 0;
  41. maxwell3d.mme_draw.instance_count = 0;
  42. maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined;
  43. }
  44. void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) {
  45. const u32 instance_count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]);
  46. const u32 element_base = parameters[4];
  47. const u32 base_instance = parameters[5];
  48. maxwell3d.regs.index_array.first = parameters[3];
  49. maxwell3d.regs.reg_array[0x446] = element_base; // vertex id base?
  50. maxwell3d.regs.index_array.count = parameters[1];
  51. maxwell3d.regs.vb_element_base = element_base;
  52. maxwell3d.regs.vb_base_instance = base_instance;
  53. maxwell3d.mme_draw.instance_count = instance_count;
  54. maxwell3d.CallMethodFromMME(0x8e3, 0x640);
  55. maxwell3d.CallMethodFromMME(0x8e4, element_base);
  56. maxwell3d.CallMethodFromMME(0x8e5, base_instance);
  57. maxwell3d.regs.draw.topology.Assign(
  58. static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0]));
  59. if (maxwell3d.ShouldExecute()) {
  60. maxwell3d.Rasterizer().Draw(true, true);
  61. }
  62. maxwell3d.regs.reg_array[0x446] = 0x0; // vertex id base?
  63. maxwell3d.regs.index_array.count = 0;
  64. maxwell3d.regs.vb_element_base = 0x0;
  65. maxwell3d.regs.vb_base_instance = 0x0;
  66. maxwell3d.mme_draw.instance_count = 0;
  67. maxwell3d.CallMethodFromMME(0x8e3, 0x640);
  68. maxwell3d.CallMethodFromMME(0x8e4, 0x0);
  69. maxwell3d.CallMethodFromMME(0x8e5, 0x0);
  70. maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined;
  71. }
  72. constexpr std::array<std::pair<u64, HLEFunction>, 3> hle_funcs{{
  73. {0x771BB18C62444DA0, &HLE_771BB18C62444DA0},
  74. {0x0D61FC9FAAC9FCAD, &HLE_0D61FC9FAAC9FCAD},
  75. {0x0217920100488FF7, &HLE_0217920100488FF7},
  76. }};
  77. class HLEMacroImpl final : public CachedMacro {
  78. public:
  79. explicit HLEMacroImpl(Engines::Maxwell3D& maxwell3d_, HLEFunction func_)
  80. : maxwell3d{maxwell3d_}, func{func_} {}
  81. void Execute(const std::vector<u32>& parameters, u32 method) override {
  82. func(maxwell3d, parameters);
  83. }
  84. private:
  85. Engines::Maxwell3D& maxwell3d;
  86. HLEFunction func;
  87. };
  88. } // Anonymous namespace
  89. HLEMacro::HLEMacro(Engines::Maxwell3D& maxwell3d_) : maxwell3d{maxwell3d_} {}
  90. HLEMacro::~HLEMacro() = default;
  91. std::unique_ptr<CachedMacro> HLEMacro::GetHLEProgram(u64 hash) const {
  92. const auto it = std::find_if(hle_funcs.cbegin(), hle_funcs.cend(),
  93. [hash](const auto& pair) { return pair.first == hash; });
  94. if (it == hle_funcs.end()) {
  95. return nullptr;
  96. }
  97. return std::make_unique<HLEMacroImpl>(maxwell3d, it->second);
  98. }
  99. } // namespace Tegra