diff options
| author | 2023-01-04 21:20:00 -0500 | |
|---|---|---|
| committer | 2023-01-04 21:20:00 -0500 | |
| commit | b78328f19a54964ef6874281d1a4d6b6ad1c34d9 (patch) | |
| tree | 239947ad53a4a06c3641d58c5d6b8daf5b3dc16a /src/video_core/macro | |
| parent | Merge pull request #9518 from gidoly/revert-9504-pg2 (diff) | |
| parent | yuzu-ui: Add setting for disabling macro HLE (diff) | |
| download | yuzu-b78328f19a54964ef6874281d1a4d6b6ad1c34d9.tar.gz yuzu-b78328f19a54964ef6874281d1a4d6b6ad1c34d9.tar.xz yuzu-b78328f19a54964ef6874281d1a4d6b6ad1c34d9.zip | |
Merge pull request #9501 from FernandoS27/yfc-rel-2
Yuzu Fried Chicken Part 1.5: MacroHLE Rework and Dynamic State
Diffstat (limited to 'src/video_core/macro')
| -rw-r--r-- | src/video_core/macro/macro.cpp | 19 | ||||
| -rw-r--r-- | src/video_core/macro/macro.h | 1 | ||||
| -rw-r--r-- | src/video_core/macro/macro_hle.cpp | 648 | ||||
| -rw-r--r-- | src/video_core/macro/macro_hle.h | 5 |
4 files changed, 569 insertions, 104 deletions
diff --git a/src/video_core/macro/macro.cpp b/src/video_core/macro/macro.cpp index 505d81c1e..82ad0477d 100644 --- a/src/video_core/macro/macro.cpp +++ b/src/video_core/macro/macro.cpp | |||
| @@ -12,7 +12,9 @@ | |||
| 12 | #include "common/assert.h" | 12 | #include "common/assert.h" |
| 13 | #include "common/fs/fs.h" | 13 | #include "common/fs/fs.h" |
| 14 | #include "common/fs/path_util.h" | 14 | #include "common/fs/path_util.h" |
| 15 | #include "common/microprofile.h" | ||
| 15 | #include "common/settings.h" | 16 | #include "common/settings.h" |
| 17 | #include "video_core/engines/maxwell_3d.h" | ||
| 16 | #include "video_core/macro/macro.h" | 18 | #include "video_core/macro/macro.h" |
| 17 | #include "video_core/macro/macro_hle.h" | 19 | #include "video_core/macro/macro_hle.h" |
| 18 | #include "video_core/macro/macro_interpreter.h" | 20 | #include "video_core/macro/macro_interpreter.h" |
| @@ -21,6 +23,8 @@ | |||
| 21 | #include "video_core/macro/macro_jit_x64.h" | 23 | #include "video_core/macro/macro_jit_x64.h" |
| 22 | #endif | 24 | #endif |
| 23 | 25 | ||
| 26 | MICROPROFILE_DEFINE(MacroHLE, "GPU", "Execute macro HLE", MP_RGB(128, 192, 192)); | ||
| 27 | |||
| 24 | namespace Tegra { | 28 | namespace Tegra { |
| 25 | 29 | ||
| 26 | static void Dump(u64 hash, std::span<const u32> code) { | 30 | static void Dump(u64 hash, std::span<const u32> code) { |
| @@ -40,8 +44,8 @@ static void Dump(u64 hash, std::span<const u32> code) { | |||
| 40 | macro_file.write(reinterpret_cast<const char*>(code.data()), code.size_bytes()); | 44 | macro_file.write(reinterpret_cast<const char*>(code.data()), code.size_bytes()); |
| 41 | } | 45 | } |
| 42 | 46 | ||
| 43 | MacroEngine::MacroEngine(Engines::Maxwell3D& maxwell3d) | 47 | MacroEngine::MacroEngine(Engines::Maxwell3D& maxwell3d_) |
| 44 | : hle_macros{std::make_unique<Tegra::HLEMacro>(maxwell3d)} {} | 48 | : hle_macros{std::make_unique<Tegra::HLEMacro>(maxwell3d_)}, maxwell3d{maxwell3d_} {} |
| 45 | 49 | ||
| 46 | MacroEngine::~MacroEngine() = default; | 50 | MacroEngine::~MacroEngine() = default; |
| 47 | 51 | ||
| @@ -59,8 +63,10 @@ void MacroEngine::Execute(u32 method, const std::vector<u32>& parameters) { | |||
| 59 | if (compiled_macro != macro_cache.end()) { | 63 | if (compiled_macro != macro_cache.end()) { |
| 60 | const auto& cache_info = compiled_macro->second; | 64 | const auto& cache_info = compiled_macro->second; |
| 61 | if (cache_info.has_hle_program) { | 65 | if (cache_info.has_hle_program) { |
| 66 | MICROPROFILE_SCOPE(MacroHLE); | ||
| 62 | cache_info.hle_program->Execute(parameters, method); | 67 | cache_info.hle_program->Execute(parameters, method); |
| 63 | } else { | 68 | } else { |
| 69 | maxwell3d.RefreshParameters(); | ||
| 64 | cache_info.lle_program->Execute(parameters, method); | 70 | cache_info.lle_program->Execute(parameters, method); |
| 65 | } | 71 | } |
| 66 | } else { | 72 | } else { |
| @@ -101,12 +107,15 @@ void MacroEngine::Execute(u32 method, const std::vector<u32>& parameters) { | |||
| 101 | } | 107 | } |
| 102 | } | 108 | } |
| 103 | 109 | ||
| 104 | if (auto hle_program = hle_macros->GetHLEProgram(cache_info.hash)) { | 110 | auto hle_program = hle_macros->GetHLEProgram(cache_info.hash); |
| 111 | if (!hle_program || Settings::values.disable_macro_hle) { | ||
| 112 | maxwell3d.RefreshParameters(); | ||
| 113 | cache_info.lle_program->Execute(parameters, method); | ||
| 114 | } else { | ||
| 105 | cache_info.has_hle_program = true; | 115 | cache_info.has_hle_program = true; |
| 106 | cache_info.hle_program = std::move(hle_program); | 116 | cache_info.hle_program = std::move(hle_program); |
| 117 | MICROPROFILE_SCOPE(MacroHLE); | ||
| 107 | cache_info.hle_program->Execute(parameters, method); | 118 | cache_info.hle_program->Execute(parameters, method); |
| 108 | } else { | ||
| 109 | cache_info.lle_program->Execute(parameters, method); | ||
| 110 | } | 119 | } |
| 111 | } | 120 | } |
| 112 | } | 121 | } |
diff --git a/src/video_core/macro/macro.h b/src/video_core/macro/macro.h index 07d97ba39..737ced9a4 100644 --- a/src/video_core/macro/macro.h +++ b/src/video_core/macro/macro.h | |||
| @@ -137,6 +137,7 @@ private: | |||
| 137 | std::unordered_map<u32, CacheInfo> macro_cache; | 137 | std::unordered_map<u32, CacheInfo> macro_cache; |
| 138 | std::unordered_map<u32, std::vector<u32>> uploaded_macro_code; | 138 | std::unordered_map<u32, std::vector<u32>> uploaded_macro_code; |
| 139 | std::unique_ptr<HLEMacro> hle_macros; | 139 | std::unique_ptr<HLEMacro> hle_macros; |
| 140 | Engines::Maxwell3D& maxwell3d; | ||
| 140 | }; | 141 | }; |
| 141 | 142 | ||
| 142 | std::unique_ptr<MacroEngine> GetMacroEngine(Engines::Maxwell3D& maxwell3d); | 143 | std::unique_ptr<MacroEngine> GetMacroEngine(Engines::Maxwell3D& maxwell3d); |
diff --git a/src/video_core/macro/macro_hle.cpp b/src/video_core/macro/macro_hle.cpp index 8549db2e4..a5476e795 100644 --- a/src/video_core/macro/macro_hle.cpp +++ b/src/video_core/macro/macro_hle.cpp | |||
| @@ -1,143 +1,593 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 3 | 3 | ||
| 4 | #include <array> | 4 | #include <array> |
| 5 | #include <vector> | 5 | #include <vector> |
| 6 | #include "common/assert.h" | ||
| 6 | #include "common/scope_exit.h" | 7 | #include "common/scope_exit.h" |
| 7 | #include "video_core/dirty_flags.h" | 8 | #include "video_core/dirty_flags.h" |
| 8 | #include "video_core/engines/draw_manager.h" | 9 | #include "video_core/engines/draw_manager.h" |
| 9 | #include "video_core/engines/maxwell_3d.h" | 10 | #include "video_core/engines/maxwell_3d.h" |
| 10 | #include "video_core/macro/macro.h" | 11 | #include "video_core/macro/macro.h" |
| 11 | #include "video_core/macro/macro_hle.h" | 12 | #include "video_core/macro/macro_hle.h" |
| 13 | #include "video_core/memory_manager.h" | ||
| 12 | #include "video_core/rasterizer_interface.h" | 14 | #include "video_core/rasterizer_interface.h" |
| 13 | 15 | ||
| 14 | namespace Tegra { | 16 | namespace Tegra { |
| 15 | namespace { | ||
| 16 | 17 | ||
| 17 | using HLEFunction = void (*)(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters); | 18 | using Maxwell3D = Engines::Maxwell3D; |
| 18 | 19 | ||
| 19 | // HLE'd functions | 20 | namespace { |
| 20 | void HLE_771BB18C62444DA0(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) { | ||
| 21 | const u32 instance_count = parameters[2] & maxwell3d.GetRegisterValue(0xD1B); | ||
| 22 | maxwell3d.draw_manager->DrawIndex( | ||
| 23 | static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0] & 0x3ffffff), | ||
| 24 | parameters[4], parameters[1], parameters[3], parameters[5], instance_count); | ||
| 25 | } | ||
| 26 | 21 | ||
| 27 | void HLE_0D61FC9FAAC9FCAD(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) { | 22 | bool IsTopologySafe(Maxwell3D::Regs::PrimitiveTopology topology) { |
| 28 | const u32 instance_count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]); | 23 | switch (topology) { |
| 29 | maxwell3d.draw_manager->DrawArray( | 24 | case Maxwell3D::Regs::PrimitiveTopology::Points: |
| 30 | static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0]), | 25 | case Maxwell3D::Regs::PrimitiveTopology::Lines: |
| 31 | parameters[3], parameters[1], parameters[4], instance_count); | 26 | case Maxwell3D::Regs::PrimitiveTopology::LineLoop: |
| 27 | case Maxwell3D::Regs::PrimitiveTopology::LineStrip: | ||
| 28 | case Maxwell3D::Regs::PrimitiveTopology::Triangles: | ||
| 29 | case Maxwell3D::Regs::PrimitiveTopology::TriangleStrip: | ||
| 30 | case Maxwell3D::Regs::PrimitiveTopology::TriangleFan: | ||
| 31 | case Maxwell3D::Regs::PrimitiveTopology::LinesAdjacency: | ||
| 32 | case Maxwell3D::Regs::PrimitiveTopology::LineStripAdjacency: | ||
| 33 | case Maxwell3D::Regs::PrimitiveTopology::TrianglesAdjacency: | ||
| 34 | case Maxwell3D::Regs::PrimitiveTopology::TriangleStripAdjacency: | ||
| 35 | case Maxwell3D::Regs::PrimitiveTopology::Patches: | ||
| 36 | return true; | ||
| 37 | case Maxwell3D::Regs::PrimitiveTopology::Quads: | ||
| 38 | case Maxwell3D::Regs::PrimitiveTopology::QuadStrip: | ||
| 39 | case Maxwell3D::Regs::PrimitiveTopology::Polygon: | ||
| 40 | default: | ||
| 41 | return false; | ||
| 42 | } | ||
| 32 | } | 43 | } |
| 33 | 44 | ||
| 34 | void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) { | 45 | class HLEMacroImpl : public CachedMacro { |
| 35 | const u32 instance_count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]); | 46 | public: |
| 36 | const u32 element_base = parameters[4]; | 47 | explicit HLEMacroImpl(Maxwell3D& maxwell3d_) : maxwell3d{maxwell3d_} {} |
| 37 | const u32 base_instance = parameters[5]; | ||
| 38 | maxwell3d.regs.vertex_id_base = element_base; | ||
| 39 | maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | ||
| 40 | maxwell3d.CallMethod(0x8e3, 0x640, true); | ||
| 41 | maxwell3d.CallMethod(0x8e4, element_base, true); | ||
| 42 | maxwell3d.CallMethod(0x8e5, base_instance, true); | ||
| 43 | |||
| 44 | maxwell3d.draw_manager->DrawIndex( | ||
| 45 | static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0]), | ||
| 46 | parameters[3], parameters[1], element_base, base_instance, instance_count); | ||
| 47 | |||
| 48 | maxwell3d.regs.vertex_id_base = 0x0; | ||
| 49 | maxwell3d.CallMethod(0x8e3, 0x640, true); | ||
| 50 | maxwell3d.CallMethod(0x8e4, 0x0, true); | ||
| 51 | maxwell3d.CallMethod(0x8e5, 0x0, true); | ||
| 52 | } | ||
| 53 | 48 | ||
| 54 | // Multidraw Indirect | 49 | protected: |
| 55 | void HLE_3F5E74B9C9A50164(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) { | 50 | Maxwell3D& maxwell3d; |
| 56 | SCOPE_EXIT({ | 51 | }; |
| 57 | // Clean everything. | 52 | |
| 58 | maxwell3d.regs.vertex_id_base = 0x0; | 53 | class HLE_DrawArrays final : public HLEMacroImpl { |
| 59 | maxwell3d.CallMethod(0x8e3, 0x640, true); | 54 | public: |
| 60 | maxwell3d.CallMethod(0x8e4, 0x0, true); | 55 | explicit HLE_DrawArrays(Maxwell3D& maxwell3d_) : HLEMacroImpl(maxwell3d_) {} |
| 61 | maxwell3d.CallMethod(0x8e5, 0x0, true); | 56 | |
| 57 | void Execute(const std::vector<u32>& parameters, [[maybe_unused]] u32 method) override { | ||
| 58 | maxwell3d.RefreshParameters(); | ||
| 59 | |||
| 60 | auto topology = static_cast<Maxwell3D::Regs::PrimitiveTopology>(parameters[0]); | ||
| 61 | maxwell3d.draw_manager->DrawArray(topology, parameters[1], parameters[2], | ||
| 62 | maxwell3d.regs.global_base_instance_index, 1); | ||
| 63 | } | ||
| 64 | }; | ||
| 65 | |||
| 66 | class HLE_DrawIndexed final : public HLEMacroImpl { | ||
| 67 | public: | ||
| 68 | explicit HLE_DrawIndexed(Maxwell3D& maxwell3d_) : HLEMacroImpl(maxwell3d_) {} | ||
| 69 | |||
| 70 | void Execute(const std::vector<u32>& parameters, [[maybe_unused]] u32 method) override { | ||
| 71 | maxwell3d.RefreshParameters(); | ||
| 72 | maxwell3d.regs.index_buffer.start_addr_high = parameters[1]; | ||
| 73 | maxwell3d.regs.index_buffer.start_addr_low = parameters[2]; | ||
| 74 | maxwell3d.regs.index_buffer.format = | ||
| 75 | static_cast<Engines::Maxwell3D::Regs::IndexFormat>(parameters[3]); | ||
| 62 | maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | 76 | maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; |
| 63 | }); | 77 | |
| 64 | const u32 start_indirect = parameters[0]; | 78 | auto topology = static_cast<Maxwell3D::Regs::PrimitiveTopology>(parameters[0]); |
| 65 | const u32 end_indirect = parameters[1]; | 79 | maxwell3d.draw_manager->DrawIndex(topology, 0, parameters[4], |
| 66 | if (start_indirect >= end_indirect) { | 80 | maxwell3d.regs.global_base_vertex_index, |
| 67 | // Nothing to do. | 81 | maxwell3d.regs.global_base_instance_index, 1); |
| 68 | return; | 82 | } |
| 69 | } | 83 | }; |
| 70 | const u32 padding = parameters[3]; | 84 | |
| 71 | const std::size_t max_draws = parameters[4]; | 85 | /* |
| 72 | 86 | * @note: these macros have two versions, a normal and extended version, with the extended version | |
| 73 | const u32 indirect_words = 5 + padding; | 87 | * also assigning the base vertex/instance. |
| 74 | const std::size_t first_draw = start_indirect; | 88 | */ |
| 75 | const std::size_t effective_draws = end_indirect - start_indirect; | 89 | template <bool extended> |
| 76 | const std::size_t last_draw = start_indirect + std::min(effective_draws, max_draws); | 90 | class HLE_DrawArraysIndirect final : public HLEMacroImpl { |
| 77 | 91 | public: | |
| 78 | for (std::size_t index = first_draw; index < last_draw; index++) { | 92 | explicit HLE_DrawArraysIndirect(Maxwell3D& maxwell3d_) : HLEMacroImpl(maxwell3d_) {} |
| 79 | const std::size_t base = index * indirect_words + 5; | 93 | |
| 80 | const u32 base_vertex = parameters[base + 3]; | 94 | void Execute(const std::vector<u32>& parameters, [[maybe_unused]] u32 method) override { |
| 81 | const u32 base_instance = parameters[base + 4]; | 95 | auto topology = static_cast<Maxwell3D::Regs::PrimitiveTopology>(parameters[0]); |
| 82 | maxwell3d.regs.vertex_id_base = base_vertex; | 96 | if (!maxwell3d.AnyParametersDirty() || !IsTopologySafe(topology)) { |
| 83 | maxwell3d.CallMethod(0x8e3, 0x640, true); | 97 | Fallback(parameters); |
| 84 | maxwell3d.CallMethod(0x8e4, base_vertex, true); | 98 | return; |
| 85 | maxwell3d.CallMethod(0x8e5, base_instance, true); | 99 | } |
| 100 | |||
| 101 | auto& params = maxwell3d.draw_manager->GetIndirectParams(); | ||
| 102 | params.is_indexed = false; | ||
| 103 | params.include_count = false; | ||
| 104 | params.count_start_address = 0; | ||
| 105 | params.indirect_start_address = maxwell3d.GetMacroAddress(1); | ||
| 106 | params.buffer_size = 4 * sizeof(u32); | ||
| 107 | params.max_draw_counts = 1; | ||
| 108 | params.stride = 0; | ||
| 109 | |||
| 110 | if constexpr (extended) { | ||
| 111 | maxwell3d.engine_state = Maxwell3D::EngineHint::OnHLEMacro; | ||
| 112 | maxwell3d.SetHLEReplacementAttributeType( | ||
| 113 | 0, 0x640, Maxwell3D::HLEReplacementAttributeType::BaseInstance); | ||
| 114 | } | ||
| 115 | |||
| 116 | maxwell3d.draw_manager->DrawArrayIndirect(topology); | ||
| 117 | |||
| 118 | if constexpr (extended) { | ||
| 119 | maxwell3d.engine_state = Maxwell3D::EngineHint::None; | ||
| 120 | maxwell3d.replace_table.clear(); | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | private: | ||
| 125 | void Fallback(const std::vector<u32>& parameters) { | ||
| 126 | SCOPE_EXIT({ | ||
| 127 | if (extended) { | ||
| 128 | maxwell3d.engine_state = Maxwell3D::EngineHint::None; | ||
| 129 | maxwell3d.replace_table.clear(); | ||
| 130 | } | ||
| 131 | }); | ||
| 132 | maxwell3d.RefreshParameters(); | ||
| 133 | const u32 instance_count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]); | ||
| 134 | |||
| 135 | auto topology = static_cast<Maxwell3D::Regs::PrimitiveTopology>(parameters[0]); | ||
| 136 | const u32 vertex_first = parameters[3]; | ||
| 137 | const u32 vertex_count = parameters[1]; | ||
| 138 | |||
| 139 | if (!IsTopologySafe(topology) && | ||
| 140 | static_cast<size_t>(maxwell3d.GetMaxCurrentVertices()) < | ||
| 141 | static_cast<size_t>(vertex_first) + static_cast<size_t>(vertex_count)) { | ||
| 142 | ASSERT_MSG(false, "Faulty draw!"); | ||
| 143 | return; | ||
| 144 | } | ||
| 145 | |||
| 146 | const u32 base_instance = parameters[4]; | ||
| 147 | if constexpr (extended) { | ||
| 148 | maxwell3d.regs.global_base_instance_index = base_instance; | ||
| 149 | maxwell3d.engine_state = Maxwell3D::EngineHint::OnHLEMacro; | ||
| 150 | maxwell3d.SetHLEReplacementAttributeType( | ||
| 151 | 0, 0x640, Maxwell3D::HLEReplacementAttributeType::BaseInstance); | ||
| 152 | } | ||
| 153 | |||
| 154 | maxwell3d.draw_manager->DrawArray(topology, vertex_first, vertex_count, base_instance, | ||
| 155 | instance_count); | ||
| 156 | |||
| 157 | if constexpr (extended) { | ||
| 158 | maxwell3d.regs.global_base_instance_index = 0; | ||
| 159 | maxwell3d.engine_state = Maxwell3D::EngineHint::None; | ||
| 160 | maxwell3d.replace_table.clear(); | ||
| 161 | } | ||
| 162 | } | ||
| 163 | }; | ||
| 164 | |||
| 165 | /* | ||
| 166 | * @note: these macros have two versions, a normal and extended version, with the extended version | ||
| 167 | * also assigning the base vertex/instance. | ||
| 168 | */ | ||
| 169 | template <bool extended> | ||
| 170 | class HLE_DrawIndexedIndirect final : public HLEMacroImpl { | ||
| 171 | public: | ||
| 172 | explicit HLE_DrawIndexedIndirect(Maxwell3D& maxwell3d_) : HLEMacroImpl(maxwell3d_) {} | ||
| 173 | |||
| 174 | void Execute(const std::vector<u32>& parameters, [[maybe_unused]] u32 method) override { | ||
| 175 | auto topology = static_cast<Maxwell3D::Regs::PrimitiveTopology>(parameters[0]); | ||
| 176 | if (!maxwell3d.AnyParametersDirty() || !IsTopologySafe(topology)) { | ||
| 177 | Fallback(parameters); | ||
| 178 | return; | ||
| 179 | } | ||
| 180 | |||
| 181 | const u32 estimate = static_cast<u32>(maxwell3d.EstimateIndexBufferSize()); | ||
| 182 | const u32 element_base = parameters[4]; | ||
| 183 | const u32 base_instance = parameters[5]; | ||
| 184 | maxwell3d.regs.vertex_id_base = element_base; | ||
| 185 | maxwell3d.regs.global_base_vertex_index = element_base; | ||
| 186 | maxwell3d.regs.global_base_instance_index = base_instance; | ||
| 187 | maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | ||
| 188 | if constexpr (extended) { | ||
| 189 | maxwell3d.engine_state = Maxwell3D::EngineHint::OnHLEMacro; | ||
| 190 | maxwell3d.SetHLEReplacementAttributeType( | ||
| 191 | 0, 0x640, Maxwell3D::HLEReplacementAttributeType::BaseVertex); | ||
| 192 | maxwell3d.SetHLEReplacementAttributeType( | ||
| 193 | 0, 0x644, Maxwell3D::HLEReplacementAttributeType::BaseInstance); | ||
| 194 | } | ||
| 195 | auto& params = maxwell3d.draw_manager->GetIndirectParams(); | ||
| 196 | params.is_indexed = true; | ||
| 197 | params.include_count = false; | ||
| 198 | params.count_start_address = 0; | ||
| 199 | params.indirect_start_address = maxwell3d.GetMacroAddress(1); | ||
| 200 | params.buffer_size = 5 * sizeof(u32); | ||
| 201 | params.max_draw_counts = 1; | ||
| 202 | params.stride = 0; | ||
| 86 | maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | 203 | maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; |
| 204 | maxwell3d.draw_manager->DrawIndexedIndirect(topology, 0, estimate); | ||
| 205 | maxwell3d.regs.vertex_id_base = 0x0; | ||
| 206 | maxwell3d.regs.global_base_vertex_index = 0x0; | ||
| 207 | maxwell3d.regs.global_base_instance_index = 0x0; | ||
| 208 | if constexpr (extended) { | ||
| 209 | maxwell3d.engine_state = Maxwell3D::EngineHint::None; | ||
| 210 | maxwell3d.replace_table.clear(); | ||
| 211 | } | ||
| 212 | } | ||
| 213 | |||
| 214 | private: | ||
| 215 | void Fallback(const std::vector<u32>& parameters) { | ||
| 216 | maxwell3d.RefreshParameters(); | ||
| 217 | const u32 instance_count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]); | ||
| 218 | const u32 element_base = parameters[4]; | ||
| 219 | const u32 base_instance = parameters[5]; | ||
| 220 | maxwell3d.regs.vertex_id_base = element_base; | ||
| 221 | maxwell3d.regs.global_base_vertex_index = element_base; | ||
| 222 | maxwell3d.regs.global_base_instance_index = base_instance; | ||
| 223 | maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | ||
| 224 | if constexpr (extended) { | ||
| 225 | maxwell3d.engine_state = Maxwell3D::EngineHint::OnHLEMacro; | ||
| 226 | maxwell3d.SetHLEReplacementAttributeType( | ||
| 227 | 0, 0x640, Maxwell3D::HLEReplacementAttributeType::BaseVertex); | ||
| 228 | maxwell3d.SetHLEReplacementAttributeType( | ||
| 229 | 0, 0x644, Maxwell3D::HLEReplacementAttributeType::BaseInstance); | ||
| 230 | } | ||
| 231 | |||
| 87 | maxwell3d.draw_manager->DrawIndex( | 232 | maxwell3d.draw_manager->DrawIndex( |
| 88 | static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[2]), | 233 | static_cast<Tegra::Maxwell3D::Regs::PrimitiveTopology>(parameters[0]), parameters[3], |
| 89 | parameters[base + 2], parameters[base], base_vertex, base_instance, | 234 | parameters[1], element_base, base_instance, instance_count); |
| 90 | parameters[base + 1]); | 235 | |
| 236 | maxwell3d.regs.vertex_id_base = 0x0; | ||
| 237 | maxwell3d.regs.global_base_vertex_index = 0x0; | ||
| 238 | maxwell3d.regs.global_base_instance_index = 0x0; | ||
| 239 | if constexpr (extended) { | ||
| 240 | maxwell3d.engine_state = Maxwell3D::EngineHint::None; | ||
| 241 | maxwell3d.replace_table.clear(); | ||
| 242 | } | ||
| 91 | } | 243 | } |
| 92 | } | 244 | }; |
| 93 | 245 | ||
| 94 | // Multi-layer Clear | 246 | class HLE_MultiLayerClear final : public HLEMacroImpl { |
| 95 | void HLE_EAD26C3E2109B06B(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) { | 247 | public: |
| 96 | ASSERT(parameters.size() == 1); | 248 | explicit HLE_MultiLayerClear(Maxwell3D& maxwell3d_) : HLEMacroImpl(maxwell3d_) {} |
| 97 | 249 | ||
| 98 | const Engines::Maxwell3D::Regs::ClearSurface clear_params{parameters[0]}; | 250 | void Execute(const std::vector<u32>& parameters, [[maybe_unused]] u32 method) override { |
| 99 | const u32 rt_index = clear_params.RT; | 251 | maxwell3d.RefreshParameters(); |
| 100 | const u32 num_layers = maxwell3d.regs.rt[rt_index].depth; | 252 | ASSERT(parameters.size() == 1); |
| 101 | ASSERT(clear_params.layer == 0); | ||
| 102 | 253 | ||
| 103 | maxwell3d.regs.clear_surface.raw = clear_params.raw; | 254 | const Maxwell3D::Regs::ClearSurface clear_params{parameters[0]}; |
| 104 | maxwell3d.draw_manager->Clear(num_layers); | 255 | const u32 rt_index = clear_params.RT; |
| 105 | } | 256 | const u32 num_layers = maxwell3d.regs.rt[rt_index].depth; |
| 257 | ASSERT(clear_params.layer == 0); | ||
| 106 | 258 | ||
| 107 | constexpr std::array<std::pair<u64, HLEFunction>, 5> hle_funcs{{ | 259 | maxwell3d.regs.clear_surface.raw = clear_params.raw; |
| 108 | {0x771BB18C62444DA0, &HLE_771BB18C62444DA0}, | 260 | maxwell3d.draw_manager->Clear(num_layers); |
| 109 | {0x0D61FC9FAAC9FCAD, &HLE_0D61FC9FAAC9FCAD}, | 261 | } |
| 110 | {0x0217920100488FF7, &HLE_0217920100488FF7}, | 262 | }; |
| 111 | {0x3F5E74B9C9A50164, &HLE_3F5E74B9C9A50164}, | 263 | |
| 112 | {0xEAD26C3E2109B06B, &HLE_EAD26C3E2109B06B}, | 264 | class HLE_MultiDrawIndexedIndirectCount final : public HLEMacroImpl { |
| 113 | }}; | 265 | public: |
| 266 | explicit HLE_MultiDrawIndexedIndirectCount(Maxwell3D& maxwell3d_) : HLEMacroImpl(maxwell3d_) {} | ||
| 267 | |||
| 268 | void Execute(const std::vector<u32>& parameters, [[maybe_unused]] u32 method) override { | ||
| 269 | const auto topology = static_cast<Maxwell3D::Regs::PrimitiveTopology>(parameters[2]); | ||
| 270 | if (!IsTopologySafe(topology)) { | ||
| 271 | Fallback(parameters); | ||
| 272 | return; | ||
| 273 | } | ||
| 274 | |||
| 275 | const u32 start_indirect = parameters[0]; | ||
| 276 | const u32 end_indirect = parameters[1]; | ||
| 277 | if (start_indirect >= end_indirect) { | ||
| 278 | // Nothing to do. | ||
| 279 | return; | ||
| 280 | } | ||
| 281 | |||
| 282 | const u32 padding = parameters[3]; // padding is in words | ||
| 283 | |||
| 284 | // size of each indirect segment | ||
| 285 | const u32 indirect_words = 5 + padding; | ||
| 286 | const u32 stride = indirect_words * sizeof(u32); | ||
| 287 | const std::size_t draw_count = end_indirect - start_indirect; | ||
| 288 | const u32 estimate = static_cast<u32>(maxwell3d.EstimateIndexBufferSize()); | ||
| 289 | maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | ||
| 290 | auto& params = maxwell3d.draw_manager->GetIndirectParams(); | ||
| 291 | params.is_indexed = true; | ||
| 292 | params.include_count = true; | ||
| 293 | params.count_start_address = maxwell3d.GetMacroAddress(4); | ||
| 294 | params.indirect_start_address = maxwell3d.GetMacroAddress(5); | ||
| 295 | params.buffer_size = stride * draw_count; | ||
| 296 | params.max_draw_counts = draw_count; | ||
| 297 | params.stride = stride; | ||
| 298 | maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | ||
| 299 | maxwell3d.engine_state = Maxwell3D::EngineHint::OnHLEMacro; | ||
| 300 | maxwell3d.SetHLEReplacementAttributeType( | ||
| 301 | 0, 0x640, Maxwell3D::HLEReplacementAttributeType::BaseVertex); | ||
| 302 | maxwell3d.SetHLEReplacementAttributeType( | ||
| 303 | 0, 0x644, Maxwell3D::HLEReplacementAttributeType::BaseInstance); | ||
| 304 | maxwell3d.SetHLEReplacementAttributeType(0, 0x648, | ||
| 305 | Maxwell3D::HLEReplacementAttributeType::DrawID); | ||
| 306 | maxwell3d.draw_manager->DrawIndexedIndirect(topology, 0, estimate); | ||
| 307 | maxwell3d.engine_state = Maxwell3D::EngineHint::None; | ||
| 308 | maxwell3d.replace_table.clear(); | ||
| 309 | } | ||
| 310 | |||
| 311 | private: | ||
| 312 | void Fallback(const std::vector<u32>& parameters) { | ||
| 313 | SCOPE_EXIT({ | ||
| 314 | // Clean everything. | ||
| 315 | maxwell3d.regs.vertex_id_base = 0x0; | ||
| 316 | maxwell3d.engine_state = Maxwell3D::EngineHint::None; | ||
| 317 | maxwell3d.replace_table.clear(); | ||
| 318 | }); | ||
| 319 | maxwell3d.RefreshParameters(); | ||
| 320 | const u32 start_indirect = parameters[0]; | ||
| 321 | const u32 end_indirect = parameters[1]; | ||
| 322 | if (start_indirect >= end_indirect) { | ||
| 323 | // Nothing to do. | ||
| 324 | return; | ||
| 325 | } | ||
| 326 | const auto topology = static_cast<Maxwell3D::Regs::PrimitiveTopology>(parameters[2]); | ||
| 327 | const u32 padding = parameters[3]; | ||
| 328 | const std::size_t max_draws = parameters[4]; | ||
| 329 | |||
| 330 | const u32 indirect_words = 5 + padding; | ||
| 331 | const std::size_t first_draw = start_indirect; | ||
| 332 | const std::size_t effective_draws = end_indirect - start_indirect; | ||
| 333 | const std::size_t last_draw = start_indirect + std::min(effective_draws, max_draws); | ||
| 334 | |||
| 335 | for (std::size_t index = first_draw; index < last_draw; index++) { | ||
| 336 | const std::size_t base = index * indirect_words + 5; | ||
| 337 | const u32 base_vertex = parameters[base + 3]; | ||
| 338 | const u32 base_instance = parameters[base + 4]; | ||
| 339 | maxwell3d.regs.vertex_id_base = base_vertex; | ||
| 340 | maxwell3d.engine_state = Maxwell3D::EngineHint::OnHLEMacro; | ||
| 341 | maxwell3d.SetHLEReplacementAttributeType( | ||
| 342 | 0, 0x640, Maxwell3D::HLEReplacementAttributeType::BaseVertex); | ||
| 343 | maxwell3d.SetHLEReplacementAttributeType( | ||
| 344 | 0, 0x644, Maxwell3D::HLEReplacementAttributeType::BaseInstance); | ||
| 345 | maxwell3d.CallMethod(0x8e3, 0x648, true); | ||
| 346 | maxwell3d.CallMethod(0x8e4, static_cast<u32>(index), true); | ||
| 347 | maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | ||
| 348 | maxwell3d.draw_manager->DrawIndex(topology, parameters[base + 2], parameters[base], | ||
| 349 | base_vertex, base_instance, parameters[base + 1]); | ||
| 350 | } | ||
| 351 | } | ||
| 352 | }; | ||
| 353 | |||
| 354 | class HLE_C713C83D8F63CCF3 final : public HLEMacroImpl { | ||
| 355 | public: | ||
| 356 | explicit HLE_C713C83D8F63CCF3(Maxwell3D& maxwell3d_) : HLEMacroImpl(maxwell3d_) {} | ||
| 357 | |||
| 358 | void Execute(const std::vector<u32>& parameters, [[maybe_unused]] u32 method) override { | ||
| 359 | maxwell3d.RefreshParameters(); | ||
| 360 | const u32 offset = (parameters[0] & 0x3FFFFFFF) << 2; | ||
| 361 | const u32 address = maxwell3d.regs.shadow_scratch[24]; | ||
| 362 | auto& const_buffer = maxwell3d.regs.const_buffer; | ||
| 363 | const_buffer.size = 0x7000; | ||
| 364 | const_buffer.address_high = (address >> 24) & 0xFF; | ||
| 365 | const_buffer.address_low = address << 8; | ||
| 366 | const_buffer.offset = offset; | ||
| 367 | } | ||
| 368 | }; | ||
| 369 | |||
| 370 | class HLE_D7333D26E0A93EDE final : public HLEMacroImpl { | ||
| 371 | public: | ||
| 372 | explicit HLE_D7333D26E0A93EDE(Maxwell3D& maxwell3d_) : HLEMacroImpl(maxwell3d_) {} | ||
| 373 | |||
| 374 | void Execute(const std::vector<u32>& parameters, [[maybe_unused]] u32 method) override { | ||
| 375 | maxwell3d.RefreshParameters(); | ||
| 376 | const size_t index = parameters[0]; | ||
| 377 | const u32 address = maxwell3d.regs.shadow_scratch[42 + index]; | ||
| 378 | const u32 size = maxwell3d.regs.shadow_scratch[47 + index]; | ||
| 379 | auto& const_buffer = maxwell3d.regs.const_buffer; | ||
| 380 | const_buffer.size = size; | ||
| 381 | const_buffer.address_high = (address >> 24) & 0xFF; | ||
| 382 | const_buffer.address_low = address << 8; | ||
| 383 | } | ||
| 384 | }; | ||
| 385 | |||
| 386 | class HLE_BindShader final : public HLEMacroImpl { | ||
| 387 | public: | ||
| 388 | explicit HLE_BindShader(Maxwell3D& maxwell3d_) : HLEMacroImpl(maxwell3d_) {} | ||
| 389 | |||
| 390 | void Execute(const std::vector<u32>& parameters, [[maybe_unused]] u32 method) override { | ||
| 391 | maxwell3d.RefreshParameters(); | ||
| 392 | auto& regs = maxwell3d.regs; | ||
| 393 | const u32 index = parameters[0]; | ||
| 394 | if ((parameters[1] - regs.shadow_scratch[28 + index]) == 0) { | ||
| 395 | return; | ||
| 396 | } | ||
| 397 | |||
| 398 | regs.pipelines[index & 0xF].offset = parameters[2]; | ||
| 399 | maxwell3d.dirty.flags[VideoCommon::Dirty::Shaders] = true; | ||
| 400 | regs.shadow_scratch[28 + index] = parameters[1]; | ||
| 401 | regs.shadow_scratch[34 + index] = parameters[2]; | ||
| 402 | |||
| 403 | const u32 address = parameters[4]; | ||
| 404 | auto& const_buffer = regs.const_buffer; | ||
| 405 | const_buffer.size = 0x10000; | ||
| 406 | const_buffer.address_high = (address >> 24) & 0xFF; | ||
| 407 | const_buffer.address_low = address << 8; | ||
| 408 | |||
| 409 | const size_t bind_group_id = parameters[3] & 0x7F; | ||
| 410 | auto& bind_group = regs.bind_groups[bind_group_id]; | ||
| 411 | bind_group.raw_config = 0x11; | ||
| 412 | maxwell3d.ProcessCBBind(bind_group_id); | ||
| 413 | } | ||
| 414 | }; | ||
| 114 | 415 | ||
| 115 | class HLEMacroImpl final : public CachedMacro { | 416 | class HLE_SetRasterBoundingBox final : public HLEMacroImpl { |
| 116 | public: | 417 | public: |
| 117 | explicit HLEMacroImpl(Engines::Maxwell3D& maxwell3d_, HLEFunction func_) | 418 | explicit HLE_SetRasterBoundingBox(Maxwell3D& maxwell3d_) : HLEMacroImpl(maxwell3d_) {} |
| 118 | : maxwell3d{maxwell3d_}, func{func_} {} | ||
| 119 | 419 | ||
| 120 | void Execute(const std::vector<u32>& parameters, u32 method) override { | 420 | void Execute(const std::vector<u32>& parameters, [[maybe_unused]] u32 method) override { |
| 121 | func(maxwell3d, parameters); | 421 | maxwell3d.RefreshParameters(); |
| 422 | const u32 raster_mode = parameters[0]; | ||
| 423 | auto& regs = maxwell3d.regs; | ||
| 424 | const u32 raster_enabled = maxwell3d.regs.conservative_raster_enable; | ||
| 425 | const u32 scratch_data = maxwell3d.regs.shadow_scratch[52]; | ||
| 426 | regs.raster_bounding_box.raw = raster_mode & 0xFFFFF00F; | ||
| 427 | regs.raster_bounding_box.pad.Assign(scratch_data & raster_enabled); | ||
| 428 | } | ||
| 429 | }; | ||
| 430 | |||
| 431 | template <size_t base_size> | ||
| 432 | class HLE_ClearConstBuffer final : public HLEMacroImpl { | ||
| 433 | public: | ||
| 434 | explicit HLE_ClearConstBuffer(Maxwell3D& maxwell3d_) : HLEMacroImpl(maxwell3d_) {} | ||
| 435 | |||
| 436 | void Execute(const std::vector<u32>& parameters, [[maybe_unused]] u32 method) override { | ||
| 437 | maxwell3d.RefreshParameters(); | ||
| 438 | static constexpr std::array<u32, base_size> zeroes{}; | ||
| 439 | auto& regs = maxwell3d.regs; | ||
| 440 | regs.const_buffer.size = static_cast<u32>(base_size); | ||
| 441 | regs.const_buffer.address_high = parameters[0]; | ||
| 442 | regs.const_buffer.address_low = parameters[1]; | ||
| 443 | regs.const_buffer.offset = 0; | ||
| 444 | maxwell3d.ProcessCBMultiData(zeroes.data(), parameters[2] * 4); | ||
| 445 | } | ||
| 446 | }; | ||
| 447 | |||
| 448 | class HLE_ClearMemory final : public HLEMacroImpl { | ||
| 449 | public: | ||
| 450 | explicit HLE_ClearMemory(Maxwell3D& maxwell3d_) : HLEMacroImpl(maxwell3d_) {} | ||
| 451 | |||
| 452 | void Execute(const std::vector<u32>& parameters, [[maybe_unused]] u32 method) override { | ||
| 453 | maxwell3d.RefreshParameters(); | ||
| 454 | |||
| 455 | const u32 needed_memory = parameters[2] / sizeof(u32); | ||
| 456 | if (needed_memory > zero_memory.size()) { | ||
| 457 | zero_memory.resize(needed_memory, 0); | ||
| 458 | } | ||
| 459 | auto& regs = maxwell3d.regs; | ||
| 460 | regs.upload.line_length_in = parameters[2]; | ||
| 461 | regs.upload.line_count = 1; | ||
| 462 | regs.upload.dest.address_high = parameters[0]; | ||
| 463 | regs.upload.dest.address_low = parameters[1]; | ||
| 464 | maxwell3d.CallMethod(static_cast<size_t>(MAXWELL3D_REG_INDEX(launch_dma)), 0x1011, true); | ||
| 465 | maxwell3d.CallMultiMethod(static_cast<size_t>(MAXWELL3D_REG_INDEX(inline_data)), | ||
| 466 | zero_memory.data(), needed_memory, needed_memory); | ||
| 122 | } | 467 | } |
| 123 | 468 | ||
| 124 | private: | 469 | private: |
| 125 | Engines::Maxwell3D& maxwell3d; | 470 | std::vector<u32> zero_memory; |
| 126 | HLEFunction func; | 471 | }; |
| 472 | |||
| 473 | class HLE_TransformFeedbackSetup final : public HLEMacroImpl { | ||
| 474 | public: | ||
| 475 | explicit HLE_TransformFeedbackSetup(Maxwell3D& maxwell3d_) : HLEMacroImpl(maxwell3d_) {} | ||
| 476 | |||
| 477 | void Execute(const std::vector<u32>& parameters, [[maybe_unused]] u32 method) override { | ||
| 478 | maxwell3d.RefreshParameters(); | ||
| 479 | |||
| 480 | auto& regs = maxwell3d.regs; | ||
| 481 | regs.transform_feedback_enabled = 1; | ||
| 482 | regs.transform_feedback.buffers[0].start_offset = 0; | ||
| 483 | regs.transform_feedback.buffers[1].start_offset = 0; | ||
| 484 | regs.transform_feedback.buffers[2].start_offset = 0; | ||
| 485 | regs.transform_feedback.buffers[3].start_offset = 0; | ||
| 486 | |||
| 487 | regs.upload.line_length_in = 4; | ||
| 488 | regs.upload.line_count = 1; | ||
| 489 | regs.upload.dest.address_high = parameters[0]; | ||
| 490 | regs.upload.dest.address_low = parameters[1]; | ||
| 491 | maxwell3d.CallMethod(static_cast<size_t>(MAXWELL3D_REG_INDEX(launch_dma)), 0x1011, true); | ||
| 492 | maxwell3d.CallMethod(static_cast<size_t>(MAXWELL3D_REG_INDEX(inline_data)), | ||
| 493 | regs.transform_feedback.controls[0].stride, true); | ||
| 494 | } | ||
| 127 | }; | 495 | }; |
| 128 | 496 | ||
| 129 | } // Anonymous namespace | 497 | } // Anonymous namespace |
| 130 | 498 | ||
| 131 | HLEMacro::HLEMacro(Engines::Maxwell3D& maxwell3d_) : maxwell3d{maxwell3d_} {} | 499 | HLEMacro::HLEMacro(Maxwell3D& maxwell3d_) : maxwell3d{maxwell3d_} { |
| 500 | builders.emplace(0xDD6A7FA92A7D2674ULL, | ||
| 501 | std::function<std::unique_ptr<CachedMacro>(Maxwell3D&)>( | ||
| 502 | [](Maxwell3D& maxwell3d__) -> std::unique_ptr<CachedMacro> { | ||
| 503 | return std::make_unique<HLE_DrawArrays>(maxwell3d__); | ||
| 504 | })); | ||
| 505 | builders.emplace(0x0D61FC9FAAC9FCADULL, | ||
| 506 | std::function<std::unique_ptr<CachedMacro>(Maxwell3D&)>( | ||
| 507 | [](Maxwell3D& maxwell3d__) -> std::unique_ptr<CachedMacro> { | ||
| 508 | return std::make_unique<HLE_DrawArraysIndirect<false>>(maxwell3d__); | ||
| 509 | })); | ||
| 510 | builders.emplace(0x8A4D173EB99A8603ULL, | ||
| 511 | std::function<std::unique_ptr<CachedMacro>(Maxwell3D&)>( | ||
| 512 | [](Maxwell3D& maxwell3d__) -> std::unique_ptr<CachedMacro> { | ||
| 513 | return std::make_unique<HLE_DrawArraysIndirect<true>>(maxwell3d__); | ||
| 514 | })); | ||
| 515 | builders.emplace(0x2DB33AADB741839CULL, | ||
| 516 | std::function<std::unique_ptr<CachedMacro>(Maxwell3D&)>( | ||
| 517 | [](Maxwell3D& maxwell3d__) -> std::unique_ptr<CachedMacro> { | ||
| 518 | return std::make_unique<HLE_DrawIndexed>(maxwell3d__); | ||
| 519 | })); | ||
| 520 | builders.emplace(0x771BB18C62444DA0ULL, | ||
| 521 | std::function<std::unique_ptr<CachedMacro>(Maxwell3D&)>( | ||
| 522 | [](Maxwell3D& maxwell3d__) -> std::unique_ptr<CachedMacro> { | ||
| 523 | return std::make_unique<HLE_DrawIndexedIndirect<false>>(maxwell3d__); | ||
| 524 | })); | ||
| 525 | builders.emplace(0x0217920100488FF7ULL, | ||
| 526 | std::function<std::unique_ptr<CachedMacro>(Maxwell3D&)>( | ||
| 527 | [](Maxwell3D& maxwell3d__) -> std::unique_ptr<CachedMacro> { | ||
| 528 | return std::make_unique<HLE_DrawIndexedIndirect<true>>(maxwell3d__); | ||
| 529 | })); | ||
| 530 | builders.emplace(0x3F5E74B9C9A50164ULL, | ||
| 531 | std::function<std::unique_ptr<CachedMacro>(Maxwell3D&)>( | ||
| 532 | [](Maxwell3D& maxwell3d__) -> std::unique_ptr<CachedMacro> { | ||
| 533 | return std::make_unique<HLE_MultiDrawIndexedIndirectCount>( | ||
| 534 | maxwell3d__); | ||
| 535 | })); | ||
| 536 | builders.emplace(0xEAD26C3E2109B06BULL, | ||
| 537 | std::function<std::unique_ptr<CachedMacro>(Maxwell3D&)>( | ||
| 538 | [](Maxwell3D& maxwell3d__) -> std::unique_ptr<CachedMacro> { | ||
| 539 | return std::make_unique<HLE_MultiLayerClear>(maxwell3d__); | ||
| 540 | })); | ||
| 541 | builders.emplace(0xC713C83D8F63CCF3ULL, | ||
| 542 | std::function<std::unique_ptr<CachedMacro>(Maxwell3D&)>( | ||
| 543 | [](Maxwell3D& maxwell3d__) -> std::unique_ptr<CachedMacro> { | ||
| 544 | return std::make_unique<HLE_C713C83D8F63CCF3>(maxwell3d__); | ||
| 545 | })); | ||
| 546 | builders.emplace(0xD7333D26E0A93EDEULL, | ||
| 547 | std::function<std::unique_ptr<CachedMacro>(Maxwell3D&)>( | ||
| 548 | [](Maxwell3D& maxwell3d__) -> std::unique_ptr<CachedMacro> { | ||
| 549 | return std::make_unique<HLE_D7333D26E0A93EDE>(maxwell3d__); | ||
| 550 | })); | ||
| 551 | builders.emplace(0xEB29B2A09AA06D38ULL, | ||
| 552 | std::function<std::unique_ptr<CachedMacro>(Maxwell3D&)>( | ||
| 553 | [](Maxwell3D& maxwell3d__) -> std::unique_ptr<CachedMacro> { | ||
| 554 | return std::make_unique<HLE_BindShader>(maxwell3d__); | ||
| 555 | })); | ||
| 556 | builders.emplace(0xDB1341DBEB4C8AF7ULL, | ||
| 557 | std::function<std::unique_ptr<CachedMacro>(Maxwell3D&)>( | ||
| 558 | [](Maxwell3D& maxwell3d__) -> std::unique_ptr<CachedMacro> { | ||
| 559 | return std::make_unique<HLE_SetRasterBoundingBox>(maxwell3d__); | ||
| 560 | })); | ||
| 561 | builders.emplace(0x6C97861D891EDf7EULL, | ||
| 562 | std::function<std::unique_ptr<CachedMacro>(Maxwell3D&)>( | ||
| 563 | [](Maxwell3D& maxwell3d__) -> std::unique_ptr<CachedMacro> { | ||
| 564 | return std::make_unique<HLE_ClearConstBuffer<0x5F00>>(maxwell3d__); | ||
| 565 | })); | ||
| 566 | builders.emplace(0xD246FDDF3A6173D7ULL, | ||
| 567 | std::function<std::unique_ptr<CachedMacro>(Maxwell3D&)>( | ||
| 568 | [](Maxwell3D& maxwell3d__) -> std::unique_ptr<CachedMacro> { | ||
| 569 | return std::make_unique<HLE_ClearConstBuffer<0x7000>>(maxwell3d__); | ||
| 570 | })); | ||
| 571 | builders.emplace(0xEE4D0004BEC8ECF4ULL, | ||
| 572 | std::function<std::unique_ptr<CachedMacro>(Maxwell3D&)>( | ||
| 573 | [](Maxwell3D& maxwell3d__) -> std::unique_ptr<CachedMacro> { | ||
| 574 | return std::make_unique<HLE_ClearMemory>(maxwell3d__); | ||
| 575 | })); | ||
| 576 | builders.emplace(0xFC0CF27F5FFAA661ULL, | ||
| 577 | std::function<std::unique_ptr<CachedMacro>(Maxwell3D&)>( | ||
| 578 | [](Maxwell3D& maxwell3d__) -> std::unique_ptr<CachedMacro> { | ||
| 579 | return std::make_unique<HLE_TransformFeedbackSetup>(maxwell3d__); | ||
| 580 | })); | ||
| 581 | } | ||
| 582 | |||
| 132 | HLEMacro::~HLEMacro() = default; | 583 | HLEMacro::~HLEMacro() = default; |
| 133 | 584 | ||
| 134 | std::unique_ptr<CachedMacro> HLEMacro::GetHLEProgram(u64 hash) const { | 585 | std::unique_ptr<CachedMacro> HLEMacro::GetHLEProgram(u64 hash) const { |
| 135 | const auto it = std::find_if(hle_funcs.cbegin(), hle_funcs.cend(), | 586 | const auto it = builders.find(hash); |
| 136 | [hash](const auto& pair) { return pair.first == hash; }); | 587 | if (it == builders.end()) { |
| 137 | if (it == hle_funcs.end()) { | ||
| 138 | return nullptr; | 588 | return nullptr; |
| 139 | } | 589 | } |
| 140 | return std::make_unique<HLEMacroImpl>(maxwell3d, it->second); | 590 | return it->second(maxwell3d); |
| 141 | } | 591 | } |
| 142 | 592 | ||
| 143 | } // namespace Tegra | 593 | } // namespace Tegra |
diff --git a/src/video_core/macro/macro_hle.h b/src/video_core/macro/macro_hle.h index 625332c9d..33f92fab1 100644 --- a/src/video_core/macro/macro_hle.h +++ b/src/video_core/macro/macro_hle.h | |||
| @@ -3,7 +3,10 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <functional> | ||
| 6 | #include <memory> | 7 | #include <memory> |
| 8 | #include <unordered_map> | ||
| 9 | |||
| 7 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 8 | 11 | ||
| 9 | namespace Tegra { | 12 | namespace Tegra { |
| @@ -23,6 +26,8 @@ public: | |||
| 23 | 26 | ||
| 24 | private: | 27 | private: |
| 25 | Engines::Maxwell3D& maxwell3d; | 28 | Engines::Maxwell3D& maxwell3d; |
| 29 | std::unordered_map<u64, std::function<std::unique_ptr<CachedMacro>(Engines::Maxwell3D&)>> | ||
| 30 | builders; | ||
| 26 | }; | 31 | }; |
| 27 | 32 | ||
| 28 | } // namespace Tegra | 33 | } // namespace Tegra |