summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/CMakeLists.txt2
-rw-r--r--src/video_core/engines/maxwell_3d.cpp2
-rw-r--r--src/video_core/engines/maxwell_3d.h4
-rw-r--r--src/video_core/macro/macro.cpp35
-rw-r--r--src/video_core/macro/macro.h19
-rw-r--r--src/video_core/macro/macro_hle.cpp108
-rw-r--r--src/video_core/macro/macro_hle.h43
-rw-r--r--src/video_core/macro/macro_interpreter.cpp3
-rw-r--r--src/video_core/macro/macro_jit_x64.cpp3
9 files changed, 209 insertions, 10 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 099bb446e..2dc752aa9 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -27,6 +27,8 @@ add_library(video_core STATIC
27 engines/shader_type.h 27 engines/shader_type.h
28 macro/macro.cpp 28 macro/macro.cpp
29 macro/macro.h 29 macro/macro.h
30 macro/macro_hle.cpp
31 macro/macro_hle.h
30 macro/macro_interpreter.cpp 32 macro/macro_interpreter.cpp
31 macro/macro_interpreter.h 33 macro/macro_interpreter.h
32 macro/macro_jit_x64.cpp 34 macro/macro_jit_x64.cpp
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index ea3c8a963..c01436295 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -128,7 +128,7 @@ void Maxwell3D::CallMacroMethod(u32 method, const std::vector<u32>& parameters)
128 ((method - MacroRegistersStart) >> 1) % static_cast<u32>(macro_positions.size()); 128 ((method - MacroRegistersStart) >> 1) % static_cast<u32>(macro_positions.size());
129 129
130 // Execute the current macro. 130 // Execute the current macro.
131 macro_engine->Execute(macro_positions[entry], parameters); 131 macro_engine->Execute(*this, macro_positions[entry], parameters);
132 if (mme_draw.current_mode != MMEDrawMode::Undefined) { 132 if (mme_draw.current_mode != MMEDrawMode::Undefined) {
133 FlushMMEInlineDraw(); 133 FlushMMEInlineDraw();
134 } 134 }
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index d5fe25065..5926c4d2d 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -1418,6 +1418,10 @@ public:
1418 return execute_on; 1418 return execute_on;
1419 } 1419 }
1420 1420
1421 VideoCore::RasterizerInterface& GetRasterizer() {
1422 return rasterizer;
1423 }
1424
1421 /// Notify a memory write has happened. 1425 /// Notify a memory write has happened.
1422 void OnMemoryWrite() { 1426 void OnMemoryWrite() {
1423 dirty.flags |= dirty.on_write_stores; 1427 dirty.flags |= dirty.on_write_stores;
diff --git a/src/video_core/macro/macro.cpp b/src/video_core/macro/macro.cpp
index 89077a2d8..c8aa2534a 100644
--- a/src/video_core/macro/macro.cpp
+++ b/src/video_core/macro/macro.cpp
@@ -2,23 +2,37 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <boost/container_hash/hash.hpp>
5#include "common/assert.h" 6#include "common/assert.h"
6#include "common/logging/log.h" 7#include "common/logging/log.h"
7#include "core/settings.h" 8#include "core/settings.h"
9#include "video_core/engines/maxwell_3d.h"
8#include "video_core/macro/macro.h" 10#include "video_core/macro/macro.h"
11#include "video_core/macro/macro_hle.h"
9#include "video_core/macro/macro_interpreter.h" 12#include "video_core/macro/macro_interpreter.h"
10#include "video_core/macro/macro_jit_x64.h" 13#include "video_core/macro/macro_jit_x64.h"
11 14
12namespace Tegra { 15namespace Tegra {
13 16
17MacroEngine::MacroEngine(Engines::Maxwell3D& maxwell3d)
18 : hle_macros{std::make_unique<Tegra::HLEMacro>(maxwell3d)} {}
19
20MacroEngine::~MacroEngine() {}
21
14void MacroEngine::AddCode(u32 method, u32 data) { 22void MacroEngine::AddCode(u32 method, u32 data) {
15 uploaded_macro_code[method].push_back(data); 23 uploaded_macro_code[method].push_back(data);
16} 24}
17 25
18void MacroEngine::Execute(u32 method, const std::vector<u32>& parameters) { 26void MacroEngine::Execute(Engines::Maxwell3D& maxwell3d, u32 method,
27 const std::vector<u32>& parameters) {
19 auto compiled_macro = macro_cache.find(method); 28 auto compiled_macro = macro_cache.find(method);
20 if (compiled_macro != macro_cache.end()) { 29 if (compiled_macro != macro_cache.end()) {
21 compiled_macro->second->Execute(parameters, method); 30 const auto& cache_info = compiled_macro->second;
31 if (cache_info.has_hle_program) {
32 cache_info.hle_program->Execute(parameters, method);
33 } else {
34 cache_info.lle_program->Execute(parameters, method);
35 }
22 } else { 36 } else {
23 // Macro not compiled, check if it's uploaded and if so, compile it 37 // Macro not compiled, check if it's uploaded and if so, compile it
24 auto macro_code = uploaded_macro_code.find(method); 38 auto macro_code = uploaded_macro_code.find(method);
@@ -26,8 +40,21 @@ void MacroEngine::Execute(u32 method, const std::vector<u32>& parameters) {
26 UNREACHABLE_MSG("Macro 0x{0:x} was not uploaded", method); 40 UNREACHABLE_MSG("Macro 0x{0:x} was not uploaded", method);
27 return; 41 return;
28 } 42 }
29 macro_cache[method] = Compile(macro_code->second); 43 auto& cache_info = macro_cache[method];
30 macro_cache[method]->Execute(parameters, method); 44 cache_info.hash = boost::hash_value(macro_code->second);
45 cache_info.lle_program = Compile(macro_code->second);
46
47 auto hle_program = hle_macros->GetHLEProgram(cache_info.hash);
48 if (hle_program.has_value()) {
49 cache_info.has_hle_program = true;
50 cache_info.hle_program = std::move(hle_program.value());
51 }
52
53 if (cache_info.has_hle_program) {
54 cache_info.hle_program->Execute(parameters, method);
55 } else {
56 cache_info.lle_program->Execute(parameters, method);
57 }
31 } 58 }
32} 59}
33 60
diff --git a/src/video_core/macro/macro.h b/src/video_core/macro/macro.h
index b76ed891f..5fa8023af 100644
--- a/src/video_core/macro/macro.h
+++ b/src/video_core/macro/macro.h
@@ -11,9 +11,11 @@
11#include "common/common_types.h" 11#include "common/common_types.h"
12 12
13namespace Tegra { 13namespace Tegra {
14
14namespace Engines { 15namespace Engines {
15class Maxwell3D; 16class Maxwell3D;
16} 17}
18
17namespace Macro { 19namespace Macro {
18constexpr std::size_t NUM_MACRO_REGISTERS = 8; 20constexpr std::size_t NUM_MACRO_REGISTERS = 8;
19enum class Operation : u32 { 21enum class Operation : u32 {
@@ -94,6 +96,8 @@ union MethodAddress {
94 96
95} // namespace Macro 97} // namespace Macro
96 98
99class HLEMacro;
100
97class CachedMacro { 101class CachedMacro {
98public: 102public:
99 virtual ~CachedMacro() = default; 103 virtual ~CachedMacro() = default;
@@ -107,20 +111,29 @@ public:
107 111
108class MacroEngine { 112class MacroEngine {
109public: 113public:
110 virtual ~MacroEngine() = default; 114 MacroEngine(Engines::Maxwell3D& maxwell3d);
115 virtual ~MacroEngine();
111 116
112 // Store the uploaded macro code to compile them when they're called. 117 // Store the uploaded macro code to compile them when they're called.
113 void AddCode(u32 method, u32 data); 118 void AddCode(u32 method, u32 data);
114 119
115 // Compiles the macro if its not in the cache, and executes the compiled macro 120 // Compiles the macro if its not in the cache, and executes the compiled macro
116 void Execute(u32 method, const std::vector<u32>& parameters); 121 void Execute(Engines::Maxwell3D& maxwell3d, u32 method, const std::vector<u32>& parameters);
117 122
118protected: 123protected:
119 virtual std::unique_ptr<CachedMacro> Compile(const std::vector<u32>& code) = 0; 124 virtual std::unique_ptr<CachedMacro> Compile(const std::vector<u32>& code) = 0;
120 125
121private: 126private:
122 std::unordered_map<u32, std::unique_ptr<CachedMacro>> macro_cache; 127 struct CacheInfo {
128 std::unique_ptr<CachedMacro> lle_program{};
129 std::unique_ptr<CachedMacro> hle_program{};
130 u64 hash{};
131 bool has_hle_program{};
132 };
133
134 std::unordered_map<u32, CacheInfo> macro_cache;
123 std::unordered_map<u32, std::vector<u32>> uploaded_macro_code; 135 std::unordered_map<u32, std::vector<u32>> uploaded_macro_code;
136 std::unique_ptr<HLEMacro> hle_macros;
124}; 137};
125 138
126std::unique_ptr<MacroEngine> GetMacroEngine(Engines::Maxwell3D& maxwell3d); 139std::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
new file mode 100644
index 000000000..51827c822
--- /dev/null
+++ b/src/video_core/macro/macro_hle.cpp
@@ -0,0 +1,108 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <unordered_map>
6#include <vector>
7#include "video_core/engines/maxwell_3d.h"
8#include "video_core/macro/macro_hle.h"
9#include "video_core/rasterizer_interface.h"
10
11namespace Tegra {
12
13// HLE'd functions
14static void HLE_771BB18C62444DA0(Engines::Maxwell3D& maxwell3d,
15 const std::vector<u32>& parameters) {
16 const u32 instance_count = parameters[2] & maxwell3d.GetRegisterValue(0xD1B);
17
18 maxwell3d.regs.draw.topology.Assign(
19 static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0] &
20 ~(0x3ffffff << 26)));
21 maxwell3d.regs.vb_base_instance = parameters[5];
22 maxwell3d.mme_draw.instance_count = instance_count;
23 maxwell3d.regs.vb_element_base = parameters[3];
24 maxwell3d.regs.index_array.count = parameters[1];
25 maxwell3d.regs.index_array.first = parameters[4];
26
27 if (maxwell3d.ShouldExecute()) {
28 maxwell3d.GetRasterizer().Draw(true, true);
29 }
30 maxwell3d.regs.index_array.count = 0;
31 maxwell3d.mme_draw.instance_count = 0;
32}
33
34static void HLE_0D61FC9FAAC9FCAD(Engines::Maxwell3D& maxwell3d,
35 const std::vector<u32>& parameters) {
36 const u32 count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]);
37
38 maxwell3d.regs.vertex_buffer.first = parameters[3];
39 maxwell3d.regs.vertex_buffer.count = parameters[1];
40 maxwell3d.regs.vb_base_instance = parameters[4];
41 maxwell3d.regs.draw.topology.Assign(
42 static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0]));
43 maxwell3d.mme_draw.instance_count = count;
44
45 if (maxwell3d.ShouldExecute()) {
46 maxwell3d.GetRasterizer().Draw(false, true);
47 }
48 maxwell3d.regs.vertex_buffer.count = 0;
49 maxwell3d.mme_draw.instance_count = 0;
50}
51
52static void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d,
53 const std::vector<u32>& parameters) {
54 const u32 instance_count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]);
55 const u32 element_base = parameters[4];
56 const u32 base_instance = parameters[5];
57 maxwell3d.regs.index_array.first = parameters[3];
58 maxwell3d.regs.reg_array[0x446] = element_base; // vertex id base?
59 maxwell3d.regs.index_array.count = parameters[1];
60 maxwell3d.regs.vb_element_base = element_base;
61 maxwell3d.regs.vb_base_instance = base_instance;
62 maxwell3d.regs.const_buffer.cb_pos = 0x640;
63 maxwell3d.mme_draw.instance_count = instance_count;
64 maxwell3d.regs.const_buffer.cb_data[0] = element_base;
65 maxwell3d.regs.const_buffer.cb_data[1] = base_instance;
66 maxwell3d.regs.draw.topology.Assign(
67 static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0]));
68 if (maxwell3d.ShouldExecute()) {
69 maxwell3d.GetRasterizer().Draw(true, true);
70 }
71 maxwell3d.regs.reg_array[0x446] = 0x0; // vertex id base?
72 maxwell3d.regs.index_array.count = 0;
73 maxwell3d.regs.vb_element_base = 0x0;
74 maxwell3d.regs.vb_base_instance = 0x0;
75 maxwell3d.regs.const_buffer.cb_pos = 0x640;
76 maxwell3d.regs.const_buffer.cb_data[0] = 0;
77 maxwell3d.regs.const_buffer.cb_data[1] = 0;
78 maxwell3d.mme_draw.instance_count = 0;
79}
80
81static const std::unordered_map<u64, HLEFunction> hle_funcs{
82 {0x771BB18C62444DA0, &HLE_771BB18C62444DA0},
83 {0x0D61FC9FAAC9FCAD, &HLE_0D61FC9FAAC9FCAD},
84 {0x0217920100488FF7, &HLE_0217920100488FF7},
85};
86
87HLEMacro::HLEMacro(Engines::Maxwell3D& maxwell3d) : maxwell3d(maxwell3d) {}
88HLEMacro::~HLEMacro() = default;
89
90std::optional<std::unique_ptr<CachedMacro>> HLEMacro::GetHLEProgram(u64 hash) const {
91 auto it = hle_funcs.find(hash);
92 if (it != hle_funcs.end()) {
93 return std::make_unique<HLEMacroImpl>(maxwell3d, it->second);
94 } else {
95 return {};
96 }
97}
98
99HLEMacroImpl::~HLEMacroImpl() = default;
100
101HLEMacroImpl::HLEMacroImpl(Engines::Maxwell3D& maxwell3d, HLEFunction func)
102 : maxwell3d(maxwell3d), func(func) {}
103
104void HLEMacroImpl::Execute(const std::vector<u32>& parameters, u32 method) {
105 func(maxwell3d, parameters);
106}
107
108} // namespace Tegra
diff --git a/src/video_core/macro/macro_hle.h b/src/video_core/macro/macro_hle.h
new file mode 100644
index 000000000..de7f43dc4
--- /dev/null
+++ b/src/video_core/macro/macro_hle.h
@@ -0,0 +1,43 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8#include <optional>
9#include <vector>
10#include "common/common_types.h"
11#include "video_core/macro/macro.h"
12
13namespace Tegra {
14
15namespace Engines {
16class Maxwell3D;
17}
18
19using HLEFunction = void (*)(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters);
20
21class HLEMacro {
22public:
23 HLEMacro(Engines::Maxwell3D& maxwell3d);
24 ~HLEMacro();
25 std::optional<std::unique_ptr<CachedMacro>> GetHLEProgram(u64 hash) const;
26
27private:
28 Engines::Maxwell3D& maxwell3d;
29};
30
31class HLEMacroImpl : public CachedMacro {
32public:
33 explicit HLEMacroImpl(Engines::Maxwell3D& maxwell3d, HLEFunction func);
34 ~HLEMacroImpl();
35
36 void Execute(const std::vector<u32>& parameters, u32 method) override;
37
38private:
39 Engines::Maxwell3D& maxwell3d;
40 HLEFunction func;
41};
42
43} // namespace Tegra
diff --git a/src/video_core/macro/macro_interpreter.cpp b/src/video_core/macro/macro_interpreter.cpp
index 5edff27aa..aa5256419 100644
--- a/src/video_core/macro/macro_interpreter.cpp
+++ b/src/video_core/macro/macro_interpreter.cpp
@@ -11,7 +11,8 @@
11MICROPROFILE_DEFINE(MacroInterp, "GPU", "Execute macro interpreter", MP_RGB(128, 128, 192)); 11MICROPROFILE_DEFINE(MacroInterp, "GPU", "Execute macro interpreter", MP_RGB(128, 128, 192));
12 12
13namespace Tegra { 13namespace Tegra {
14MacroInterpreter::MacroInterpreter(Engines::Maxwell3D& maxwell3d) : maxwell3d(maxwell3d) {} 14MacroInterpreter::MacroInterpreter(Engines::Maxwell3D& maxwell3d)
15 : MacroEngine::MacroEngine(maxwell3d), maxwell3d(maxwell3d) {}
15 16
16std::unique_ptr<CachedMacro> MacroInterpreter::Compile(const std::vector<u32>& code) { 17std::unique_ptr<CachedMacro> MacroInterpreter::Compile(const std::vector<u32>& code) {
17 return std::make_unique<MacroInterpreterImpl>(maxwell3d, code); 18 return std::make_unique<MacroInterpreterImpl>(maxwell3d, code);
diff --git a/src/video_core/macro/macro_jit_x64.cpp b/src/video_core/macro/macro_jit_x64.cpp
index 30abb66e5..07292702f 100644
--- a/src/video_core/macro/macro_jit_x64.cpp
+++ b/src/video_core/macro/macro_jit_x64.cpp
@@ -28,7 +28,8 @@ static const std::bitset<32> PERSISTENT_REGISTERS = Common::X64::BuildRegSet({
28 BRANCH_HOLDER, 28 BRANCH_HOLDER,
29}); 29});
30 30
31MacroJITx64::MacroJITx64(Engines::Maxwell3D& maxwell3d) : maxwell3d(maxwell3d) {} 31MacroJITx64::MacroJITx64(Engines::Maxwell3D& maxwell3d)
32 : MacroEngine::MacroEngine(maxwell3d), maxwell3d(maxwell3d) {}
32 33
33std::unique_ptr<CachedMacro> MacroJITx64::Compile(const std::vector<u32>& code) { 34std::unique_ptr<CachedMacro> MacroJITx64::Compile(const std::vector<u32>& code) {
34 return std::make_unique<MacroJITx64Impl>(maxwell3d, code); 35 return std::make_unique<MacroJITx64Impl>(maxwell3d, code);