summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2016-12-17 01:21:16 -0800
committerGravatar Yuri Kunde Schlesner2017-01-25 18:53:24 -0800
commit114d6b2f97eb62c7d8c958ebb391b70b026130f9 (patch)
tree8600239b8ee804b78bc2c60fb6285a2e8cf2c4fa /src
parentVideoCore/Shader: Rename shader_jit_x64{ => _compiler}.{cpp,h} (diff)
downloadyuzu-114d6b2f97eb62c7d8c958ebb391b70b026130f9.tar.gz
yuzu-114d6b2f97eb62c7d8c958ebb391b70b026130f9.tar.xz
yuzu-114d6b2f97eb62c7d8c958ebb391b70b026130f9.zip
VideoCore/Shader: Split interpreter and JIT into separate ShaderEngines
Diffstat (limited to 'src')
-rw-r--r--src/video_core/CMakeLists.txt2
-rw-r--r--src/video_core/pica.cpp2
-rw-r--r--src/video_core/shader/shader.cpp92
-rw-r--r--src/video_core/shader/shader.h5
-rw-r--r--src/video_core/shader/shader_interpreter.cpp39
-rw-r--r--src/video_core/shader/shader_interpreter.h19
-rw-r--r--src/video_core/shader/shader_jit_x64.cpp56
-rw-r--r--src/video_core/shader/shader_jit_x64.h35
8 files changed, 153 insertions, 97 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 36397cce9..d55b84ce0 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -50,9 +50,11 @@ set(HEADERS
50 50
51if(ARCHITECTURE_x86_64) 51if(ARCHITECTURE_x86_64)
52 set(SRCS ${SRCS} 52 set(SRCS ${SRCS}
53 shader/shader_jit_x64.cpp
53 shader/shader_jit_x64_compiler.cpp) 54 shader/shader_jit_x64_compiler.cpp)
54 55
55 set(HEADERS ${HEADERS} 56 set(HEADERS ${HEADERS}
57 shader/shader_jit_x64.h
56 shader/shader_jit_x64_compiler.h) 58 shader/shader_jit_x64_compiler.h)
57endif() 59endif()
58 60
diff --git a/src/video_core/pica.cpp b/src/video_core/pica.cpp
index ce2bd455e..b4a77c632 100644
--- a/src/video_core/pica.cpp
+++ b/src/video_core/pica.cpp
@@ -499,7 +499,7 @@ void Init() {
499} 499}
500 500
501void Shutdown() { 501void Shutdown() {
502 Shader::ClearCache(); 502 Shader::Shutdown();
503} 503}
504 504
505template <typename T> 505template <typename T>
diff --git a/src/video_core/shader/shader.cpp b/src/video_core/shader/shader.cpp
index 97c6519d6..b30dae476 100644
--- a/src/video_core/shader/shader.cpp
+++ b/src/video_core/shader/shader.cpp
@@ -2,14 +2,8 @@
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 <atomic>
6#include <cmath> 5#include <cmath>
7#include <cstring> 6#include <cstring>
8#include <unordered_map>
9#include <utility>
10#include <boost/range/algorithm/fill.hpp>
11#include "common/bit_field.h"
12#include "common/hash.h"
13#include "common/logging/log.h" 7#include "common/logging/log.h"
14#include "common/microprofile.h" 8#include "common/microprofile.h"
15#include "video_core/pica.h" 9#include "video_core/pica.h"
@@ -17,7 +11,7 @@
17#include "video_core/shader/shader.h" 11#include "video_core/shader/shader.h"
18#include "video_core/shader/shader_interpreter.h" 12#include "video_core/shader/shader_interpreter.h"
19#ifdef ARCHITECTURE_x86_64 13#ifdef ARCHITECTURE_x86_64
20#include "video_core/shader/shader_jit_x64_compiler.h" 14#include "video_core/shader/shader_jit_x64.h"
21#endif // ARCHITECTURE_x86_64 15#endif // ARCHITECTURE_x86_64
22#include "video_core/video_core.h" 16#include "video_core/video_core.h"
23 17
@@ -87,93 +81,33 @@ void UnitState::LoadInputVertex(const InputVertex& input, int num_attributes) {
87 conditional_code[1] = false; 81 conditional_code[1] = false;
88} 82}
89 83
90class MergedShaderEngine : public ShaderEngine { 84MICROPROFILE_DEFINE(GPU_Shader, "GPU", "Shader", MP_RGB(50, 50, 240));
91public:
92 void SetupBatch(const ShaderSetup* setup) override;
93 void Run(UnitState& state, unsigned int entry_point) const override;
94 DebugData<true> ProduceDebugInfo(const InputVertex& input, int num_attributes,
95 unsigned int entry_point) const override;
96
97private:
98 const ShaderSetup* setup = nullptr;
99};
100
101#ifdef ARCHITECTURE_x86_64
102static std::unordered_map<u64, std::unique_ptr<JitShader>> shader_map;
103static const JitShader* jit_shader;
104#endif // ARCHITECTURE_x86_64
105 85
106void ClearCache() {
107#ifdef ARCHITECTURE_x86_64 86#ifdef ARCHITECTURE_x86_64
108 shader_map.clear(); 87static std::unique_ptr<JitX64Engine> jit_engine;
109#endif // ARCHITECTURE_x86_64 88#endif // ARCHITECTURE_x86_64
110} 89static InterpreterEngine interpreter_engine;
111
112void MergedShaderEngine::SetupBatch(const ShaderSetup* setup_) {
113 setup = setup_;
114 if (setup == nullptr)
115 return;
116 90
91ShaderEngine* GetEngine() {
117#ifdef ARCHITECTURE_x86_64 92#ifdef ARCHITECTURE_x86_64
93 // TODO(yuriks): Re-initialize on each change rather than being persistent
118 if (VideoCore::g_shader_jit_enabled) { 94 if (VideoCore::g_shader_jit_enabled) {
119 u64 code_hash = Common::ComputeHash64(&setup->program_code, sizeof(setup->program_code)); 95 if (jit_engine == nullptr) {
120 u64 swizzle_hash = Common::ComputeHash64(&setup->swizzle_data, sizeof(setup->swizzle_data)); 96 jit_engine = std::make_unique<JitX64Engine>();
121
122 u64 cache_key = code_hash ^ swizzle_hash;
123 auto iter = shader_map.find(cache_key);
124 if (iter != shader_map.end()) {
125 jit_shader = iter->second.get();
126 } else {
127 auto shader = std::make_unique<JitShader>();
128 shader->Compile();
129 jit_shader = shader.get();
130 shader_map[cache_key] = std::move(shader);
131 } 97 }
98 return jit_engine.get();
132 } 99 }
133#endif // ARCHITECTURE_x86_64 100#endif // ARCHITECTURE_x86_64
134}
135
136MICROPROFILE_DEFINE(GPU_Shader, "GPU", "Shader", MP_RGB(50, 50, 240));
137
138void MergedShaderEngine::Run(UnitState& state, unsigned int entry_point) const {
139 ASSERT(setup != nullptr);
140 ASSERT(entry_point < 1024);
141 101
142 MICROPROFILE_SCOPE(GPU_Shader); 102 return &interpreter_engine;
103}
143 104
105void Shutdown() {
144#ifdef ARCHITECTURE_x86_64 106#ifdef ARCHITECTURE_x86_64
145 if (VideoCore::g_shader_jit_enabled) { 107 jit_engine = nullptr;
146 jit_shader->Run(*setup, state, entry_point);
147 } else {
148 DebugData<false> dummy_debug_data;
149 RunInterpreter(*setup, state, dummy_debug_data, entry_point);
150 }
151#else
152 DebugData<false> dummy_debug_data;
153 RunInterpreter(*setup, state, dummy_debug_data, entry_point);
154#endif // ARCHITECTURE_x86_64 108#endif // ARCHITECTURE_x86_64
155} 109}
156 110
157DebugData<true> MergedShaderEngine::ProduceDebugInfo(const InputVertex& input, int num_attributes,
158 unsigned int entry_point) const {
159 ASSERT(setup != nullptr);
160 ASSERT(entry_point < 1024);
161
162 UnitState state;
163 DebugData<true> debug_data;
164
165 // Setup input register table
166 boost::fill(state.registers.input, Math::Vec4<float24>::AssignToAll(float24::Zero()));
167 state.LoadInputVertex(input, num_attributes);
168 RunInterpreter(*setup, state, debug_data, entry_point);
169 return debug_data;
170}
171
172ShaderEngine* GetEngine() {
173 static MergedShaderEngine merged_engine;
174 return &merged_engine;
175}
176
177} // namespace Shader 111} // namespace Shader
178 112
179} // namespace Pica 113} // namespace Pica
diff --git a/src/video_core/shader/shader.h b/src/video_core/shader/shader.h
index 899fb2607..2afd1024f 100644
--- a/src/video_core/shader/shader.h
+++ b/src/video_core/shader/shader.h
@@ -6,7 +6,6 @@
6 6
7#include <array> 7#include <array>
8#include <cstddef> 8#include <cstddef>
9#include <memory>
10#include <type_traits> 9#include <type_traits>
11#include <nihstro/shader_bytecode.h> 10#include <nihstro/shader_bytecode.h>
12#include "common/assert.h" 11#include "common/assert.h"
@@ -152,9 +151,6 @@ struct UnitState {
152 void LoadInputVertex(const InputVertex& input, int num_attributes); 151 void LoadInputVertex(const InputVertex& input, int num_attributes);
153}; 152};
154 153
155/// Clears the shader cache
156void ClearCache();
157
158struct ShaderSetup { 154struct ShaderSetup {
159 struct { 155 struct {
160 // The float uniforms are accessed by the shader JIT using SSE instructions, and are 156 // The float uniforms are accessed by the shader JIT using SSE instructions, and are
@@ -210,6 +206,7 @@ public:
210 206
211// TODO(yuriks): Remove and make it non-global state somewhere 207// TODO(yuriks): Remove and make it non-global state somewhere
212ShaderEngine* GetEngine(); 208ShaderEngine* GetEngine();
209void Shutdown();
213 210
214} // namespace Shader 211} // namespace Shader
215 212
diff --git a/src/video_core/shader/shader_interpreter.cpp b/src/video_core/shader/shader_interpreter.cpp
index 20fb9754b..8e2b8c548 100644
--- a/src/video_core/shader/shader_interpreter.cpp
+++ b/src/video_core/shader/shader_interpreter.cpp
@@ -7,10 +7,12 @@
7#include <cmath> 7#include <cmath>
8#include <numeric> 8#include <numeric>
9#include <boost/container/static_vector.hpp> 9#include <boost/container/static_vector.hpp>
10#include <boost/range/algorithm/fill.hpp>
10#include <nihstro/shader_bytecode.h> 11#include <nihstro/shader_bytecode.h>
11#include "common/assert.h" 12#include "common/assert.h"
12#include "common/common_types.h" 13#include "common/common_types.h"
13#include "common/logging/log.h" 14#include "common/logging/log.h"
15#include "common/microprofile.h"
14#include "common/vector_math.h" 16#include "common/vector_math.h"
15#include "video_core/pica_state.h" 17#include "video_core/pica_state.h"
16#include "video_core/pica_types.h" 18#include "video_core/pica_types.h"
@@ -37,8 +39,8 @@ struct CallStackElement {
37}; 39};
38 40
39template <bool Debug> 41template <bool Debug>
40void RunInterpreter(const ShaderSetup& setup, UnitState& state, DebugData<Debug>& debug_data, 42static void RunInterpreter(const ShaderSetup& setup, UnitState& state, DebugData<Debug>& debug_data,
41 unsigned offset) { 43 unsigned offset) {
42 // TODO: Is there a maximal size for this? 44 // TODO: Is there a maximal size for this?
43 boost::container::static_vector<CallStackElement, 16> call_stack; 45 boost::container::static_vector<CallStackElement, 16> call_stack;
44 u32 program_counter = offset; 46 u32 program_counter = offset;
@@ -647,9 +649,36 @@ void RunInterpreter(const ShaderSetup& setup, UnitState& state, DebugData<Debug>
647 } 649 }
648} 650}
649 651
650// Explicit instantiation 652void InterpreterEngine::SetupBatch(const ShaderSetup* setup_) {
651template void RunInterpreter(const ShaderSetup&, UnitState&, DebugData<false>&, unsigned offset); 653 setup = setup_;
652template void RunInterpreter(const ShaderSetup&, UnitState&, DebugData<true>&, unsigned offset); 654}
655
656MICROPROFILE_DECLARE(GPU_Shader);
657
658void InterpreterEngine::Run(UnitState& state, unsigned int entry_point) const {
659 ASSERT(setup != nullptr);
660 ASSERT(entry_point < 1024);
661
662 MICROPROFILE_SCOPE(GPU_Shader);
663
664 DebugData<false> dummy_debug_data;
665 RunInterpreter(*setup, state, dummy_debug_data, entry_point);
666}
667
668DebugData<true> InterpreterEngine::ProduceDebugInfo(const InputVertex& input, int num_attributes,
669 unsigned int entry_point) const {
670 ASSERT(setup != nullptr);
671 ASSERT(entry_point < 1024);
672
673 UnitState state;
674 DebugData<true> debug_data;
675
676 // Setup input register table
677 boost::fill(state.registers.input, Math::Vec4<float24>::AssignToAll(float24::Zero()));
678 state.LoadInputVertex(input, num_attributes);
679 RunInterpreter(*setup, state, debug_data, entry_point);
680 return debug_data;
681}
653 682
654} // namespace 683} // namespace
655 684
diff --git a/src/video_core/shader/shader_interpreter.h b/src/video_core/shader/shader_interpreter.h
index 3237b50b3..43c1ed5ea 100644
--- a/src/video_core/shader/shader_interpreter.h
+++ b/src/video_core/shader/shader_interpreter.h
@@ -4,19 +4,22 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "video_core/shader/shader.h"
8
7namespace Pica { 9namespace Pica {
8 10
9namespace Shader { 11namespace Shader {
10 12
11struct ShaderSetup; 13class InterpreterEngine final : public ShaderEngine {
12struct UnitState; 14public:
13 15 void SetupBatch(const ShaderSetup* setup) override;
14template <bool Debug> 16 void Run(UnitState& state, unsigned int entry_point) const override;
15struct DebugData; 17 DebugData<true> ProduceDebugInfo(const InputVertex& input, int num_attributes,
18 unsigned int entry_point) const override;
16 19
17template <bool Debug> 20private:
18void RunInterpreter(const ShaderSetup& setup, UnitState& state, DebugData<Debug>& debug_data, 21 const ShaderSetup* setup = nullptr;
19 unsigned offset); 22};
20 23
21} // namespace 24} // namespace
22 25
diff --git a/src/video_core/shader/shader_jit_x64.cpp b/src/video_core/shader/shader_jit_x64.cpp
new file mode 100644
index 000000000..fea79538a
--- /dev/null
+++ b/src/video_core/shader/shader_jit_x64.cpp
@@ -0,0 +1,56 @@
1// Copyright 2016 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/hash.h"
6#include "common/microprofile.h"
7#include "video_core/shader/shader.h"
8#include "video_core/shader/shader_jit_x64.h"
9#include "video_core/shader/shader_jit_x64_compiler.h"
10
11namespace Pica {
12namespace Shader {
13
14JitX64Engine::JitX64Engine() = default;
15JitX64Engine::~JitX64Engine() = default;
16
17void JitX64Engine::SetupBatch(const ShaderSetup* setup_) {
18 cached_shader = nullptr;
19 setup = setup_;
20 if (setup == nullptr)
21 return;
22
23 u64 code_hash = Common::ComputeHash64(&setup->program_code, sizeof(setup->program_code));
24 u64 swizzle_hash = Common::ComputeHash64(&setup->swizzle_data, sizeof(setup->swizzle_data));
25
26 u64 cache_key = code_hash ^ swizzle_hash;
27 auto iter = cache.find(cache_key);
28 if (iter != cache.end()) {
29 cached_shader = iter->second.get();
30 } else {
31 auto shader = std::make_unique<JitShader>();
32 shader->Compile();
33 cached_shader = shader.get();
34 cache.emplace_hint(iter, cache_key, std::move(shader));
35 }
36}
37
38MICROPROFILE_DECLARE(GPU_Shader);
39
40void JitX64Engine::Run(UnitState& state, unsigned int entry_point) const {
41 ASSERT(setup != nullptr);
42 ASSERT(cached_shader != nullptr);
43 ASSERT(entry_point < 1024);
44
45 MICROPROFILE_SCOPE(GPU_Shader);
46
47 cached_shader->Run(*setup, state, entry_point);
48}
49
50DebugData<true> JitX64Engine::ProduceDebugInfo(const InputVertex& input, int num_attributes,
51 unsigned int entry_point) const {
52 UNIMPLEMENTED_MSG("Shader tracing/debugging is not supported by the JIT.");
53}
54
55} // namespace Shader
56} // namespace Pica
diff --git a/src/video_core/shader/shader_jit_x64.h b/src/video_core/shader/shader_jit_x64.h
new file mode 100644
index 000000000..df18de2c2
--- /dev/null
+++ b/src/video_core/shader/shader_jit_x64.h
@@ -0,0 +1,35 @@
1// Copyright 2016 Citra 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 <unordered_map>
9#include "common/common_types.h"
10#include "video_core/shader/shader.h"
11
12namespace Pica {
13namespace Shader {
14
15class JitShader;
16
17class JitX64Engine final : public ShaderEngine {
18public:
19 JitX64Engine();
20 ~JitX64Engine() override;
21
22 void SetupBatch(const ShaderSetup* setup) override;
23 void Run(UnitState& state, unsigned int entry_point) const override;
24 DebugData<true> ProduceDebugInfo(const InputVertex& input, int num_attributes,
25 unsigned int entry_point) const override;
26
27private:
28 const ShaderSetup* setup = nullptr;
29
30 std::unordered_map<u64, std::unique_ptr<JitShader>> cache;
31 const JitShader* cached_shader = nullptr;
32};
33
34} // namespace Shader
35} // namespace Pica