summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/color.h4
-rw-r--r--src/core/cpu_manager.cpp29
-rw-r--r--src/core/file_sys/registered_cache.cpp33
-rw-r--r--src/video_core/engines/fermi_2d.cpp10
-rw-r--r--src/video_core/engines/fermi_2d.h9
-rw-r--r--src/video_core/engines/kepler_compute.cpp17
-rw-r--r--src/video_core/engines/kepler_compute.h16
-rw-r--r--src/video_core/engines/maxwell_3d.cpp35
-rw-r--r--src/video_core/engines/maxwell_3d.h21
-rw-r--r--src/video_core/fence_manager.h5
-rw-r--r--src/video_core/gpu.cpp31
-rw-r--r--src/video_core/gpu.h13
-rw-r--r--src/video_core/gpu_asynch.cpp10
-rw-r--r--src/video_core/gpu_asynch.h4
-rw-r--r--src/video_core/gpu_synch.cpp8
-rw-r--r--src/video_core/gpu_synch.h6
-rw-r--r--src/video_core/macro/macro_hle.cpp6
-rw-r--r--src/video_core/memory_manager.cpp12
-rw-r--r--src/video_core/memory_manager.h7
-rw-r--r--src/video_core/renderer_base.cpp4
-rw-r--r--src/video_core/renderer_base.h17
-rw-r--r--src/video_core/renderer_opengl/gl_fence_manager.cpp7
-rw-r--r--src/video_core/renderer_opengl/gl_fence_manager.h1
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.h2
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp11
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.h11
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.cpp6
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.h5
-rw-r--r--src/video_core/video_core.cpp32
30 files changed, 209 insertions, 165 deletions
diff --git a/src/common/color.h b/src/common/color.h
index 381d6332e..bbcac858e 100644
--- a/src/common/color.h
+++ b/src/common/color.h
@@ -10,7 +10,7 @@
10#include "common/swap.h" 10#include "common/swap.h"
11#include "common/vector_math.h" 11#include "common/vector_math.h"
12 12
13namespace Color { 13namespace Common::Color {
14 14
15/// Convert a 1-bit color component to 8 bit 15/// Convert a 1-bit color component to 8 bit
16[[nodiscard]] constexpr u8 Convert1To8(u8 value) { 16[[nodiscard]] constexpr u8 Convert1To8(u8 value) {
@@ -268,4 +268,4 @@ inline void EncodeX24S8(u8 stencil, u8* bytes) {
268 bytes[3] = stencil; 268 bytes[3] = stencil;
269} 269}
270 270
271} // namespace Color 271} // namespace Common::Color
diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp
index 358943429..ef0bae556 100644
--- a/src/core/cpu_manager.cpp
+++ b/src/core/cpu_manager.cpp
@@ -41,9 +41,9 @@ void CpuManager::Shutdown() {
41 running_mode = false; 41 running_mode = false;
42 Pause(false); 42 Pause(false);
43 if (is_multicore) { 43 if (is_multicore) {
44 for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { 44 for (auto& data : core_data) {
45 core_data[core].host_thread->join(); 45 data.host_thread->join();
46 core_data[core].host_thread.reset(); 46 data.host_thread.reset();
47 } 47 }
48 } else { 48 } else {
49 core_data[0].host_thread->join(); 49 core_data[0].host_thread->join();
@@ -166,25 +166,23 @@ void CpuManager::MultiCorePause(bool paused) {
166 bool all_not_barrier = false; 166 bool all_not_barrier = false;
167 while (!all_not_barrier) { 167 while (!all_not_barrier) {
168 all_not_barrier = true; 168 all_not_barrier = true;
169 for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { 169 for (const auto& data : core_data) {
170 all_not_barrier &= 170 all_not_barrier &= !data.is_running.load() && data.initialized.load();
171 !core_data[core].is_running.load() && core_data[core].initialized.load();
172 } 171 }
173 } 172 }
174 for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { 173 for (auto& data : core_data) {
175 core_data[core].enter_barrier->Set(); 174 data.enter_barrier->Set();
176 } 175 }
177 if (paused_state.load()) { 176 if (paused_state.load()) {
178 bool all_barrier = false; 177 bool all_barrier = false;
179 while (!all_barrier) { 178 while (!all_barrier) {
180 all_barrier = true; 179 all_barrier = true;
181 for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { 180 for (const auto& data : core_data) {
182 all_barrier &= 181 all_barrier &= data.is_paused.load() && data.initialized.load();
183 core_data[core].is_paused.load() && core_data[core].initialized.load();
184 } 182 }
185 } 183 }
186 for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { 184 for (auto& data : core_data) {
187 core_data[core].exit_barrier->Set(); 185 data.exit_barrier->Set();
188 } 186 }
189 } 187 }
190 } else { 188 } else {
@@ -192,9 +190,8 @@ void CpuManager::MultiCorePause(bool paused) {
192 bool all_barrier = false; 190 bool all_barrier = false;
193 while (!all_barrier) { 191 while (!all_barrier) {
194 all_barrier = true; 192 all_barrier = true;
195 for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { 193 for (const auto& data : core_data) {
196 all_barrier &= 194 all_barrier &= data.is_paused.load() && data.initialized.load();
197 core_data[core].is_paused.load() && core_data[core].initialized.load();
198 } 195 }
199 } 196 }
200 /// Don't release the barrier 197 /// Don't release the barrier
diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp
index e42b677f7..da01002d5 100644
--- a/src/core/file_sys/registered_cache.cpp
+++ b/src/core/file_sys/registered_cache.cpp
@@ -257,8 +257,7 @@ std::vector<NcaID> PlaceholderCache::List() const {
257 for (const auto& sdir : dir->GetSubdirectories()) { 257 for (const auto& sdir : dir->GetSubdirectories()) {
258 for (const auto& file : sdir->GetFiles()) { 258 for (const auto& file : sdir->GetFiles()) {
259 const auto name = file->GetName(); 259 const auto name = file->GetName();
260 if (name.length() == 36 && name[32] == '.' && name[33] == 'n' && name[34] == 'c' && 260 if (name.length() == 36 && name.ends_with(".nca")) {
261 name[35] == 'a') {
262 out.push_back(Common::HexStringToArray<0x10>(name.substr(0, 32))); 261 out.push_back(Common::HexStringToArray<0x10>(name.substr(0, 32)));
263 } 262 }
264 } 263 }
@@ -621,25 +620,25 @@ InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_ex
621 620
622InstallResult RegisteredCache::InstallEntry(const NCA& nca, TitleType type, 621InstallResult RegisteredCache::InstallEntry(const NCA& nca, TitleType type,
623 bool overwrite_if_exists, const VfsCopyFunction& copy) { 622 bool overwrite_if_exists, const VfsCopyFunction& copy) {
624 CNMTHeader header{ 623 const CNMTHeader header{
625 nca.GetTitleId(), // Title ID 624 .title_id = nca.GetTitleId(),
626 0, // Ignore/Default title version 625 .title_version = 0,
627 type, // Type 626 .type = type,
628 {}, // Padding 627 .reserved = {},
629 0x10, // Default table offset 628 .table_offset = 0x10,
630 1, // 1 Content Entry 629 .number_content_entries = 1,
631 0, // No Meta Entries 630 .number_meta_entries = 0,
632 {}, // Padding 631 .attributes = 0,
633 {}, // Reserved 1 632 .reserved2 = {},
634 0, // Is committed 633 .is_committed = 0,
635 0, // Required download system version 634 .required_download_system_version = 0,
636 {}, // Reserved 2 635 .reserved3 = {},
637 }; 636 };
638 OptionalHeader opt_header{0, 0}; 637 const OptionalHeader opt_header{0, 0};
639 ContentRecord c_rec{{}, {}, {}, GetCRTypeFromNCAType(nca.GetType()), {}}; 638 ContentRecord c_rec{{}, {}, {}, GetCRTypeFromNCAType(nca.GetType()), {}};
640 const auto& data = nca.GetBaseFile()->ReadBytes(0x100000); 639 const auto& data = nca.GetBaseFile()->ReadBytes(0x100000);
641 mbedtls_sha256_ret(data.data(), data.size(), c_rec.hash.data(), 0); 640 mbedtls_sha256_ret(data.data(), data.size(), c_rec.hash.data(), 0);
642 memcpy(&c_rec.nca_id, &c_rec.hash, 16); 641 std::memcpy(&c_rec.nca_id, &c_rec.hash, 16);
643 const CNMT new_cnmt(header, opt_header, {c_rec}, {}); 642 const CNMT new_cnmt(header, opt_header, {c_rec}, {});
644 if (!RawInstallYuzuMeta(new_cnmt)) { 643 if (!RawInstallYuzuMeta(new_cnmt)) {
645 return InstallResult::ErrorMetaFailed; 644 return InstallResult::ErrorMetaFailed;
diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp
index ff10ff40d..6e50661a3 100644
--- a/src/video_core/engines/fermi_2d.cpp
+++ b/src/video_core/engines/fermi_2d.cpp
@@ -10,7 +10,13 @@
10 10
11namespace Tegra::Engines { 11namespace Tegra::Engines {
12 12
13Fermi2D::Fermi2D(VideoCore::RasterizerInterface& rasterizer) : rasterizer{rasterizer} {} 13Fermi2D::Fermi2D() = default;
14
15Fermi2D::~Fermi2D() = default;
16
17void Fermi2D::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
18 rasterizer = &rasterizer_;
19}
14 20
15void Fermi2D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { 21void Fermi2D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
16 ASSERT_MSG(method < Regs::NUM_REGS, 22 ASSERT_MSG(method < Regs::NUM_REGS,
@@ -87,7 +93,7 @@ void Fermi2D::HandleSurfaceCopy() {
87 copy_config.src_rect = src_rect; 93 copy_config.src_rect = src_rect;
88 copy_config.dst_rect = dst_rect; 94 copy_config.dst_rect = dst_rect;
89 95
90 if (!rasterizer.AccelerateSurfaceCopy(regs.src, regs.dst, copy_config)) { 96 if (!rasterizer->AccelerateSurfaceCopy(regs.src, regs.dst, copy_config)) {
91 UNIMPLEMENTED(); 97 UNIMPLEMENTED();
92 } 98 }
93} 99}
diff --git a/src/video_core/engines/fermi_2d.h b/src/video_core/engines/fermi_2d.h
index 8f37d053f..213abfaae 100644
--- a/src/video_core/engines/fermi_2d.h
+++ b/src/video_core/engines/fermi_2d.h
@@ -34,8 +34,11 @@ namespace Tegra::Engines {
34 34
35class Fermi2D final : public EngineInterface { 35class Fermi2D final : public EngineInterface {
36public: 36public:
37 explicit Fermi2D(VideoCore::RasterizerInterface& rasterizer); 37 explicit Fermi2D();
38 ~Fermi2D() = default; 38 ~Fermi2D();
39
40 /// Binds a rasterizer to this engine.
41 void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
39 42
40 /// Write the value to the register identified by method. 43 /// Write the value to the register identified by method.
41 void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; 44 void CallMethod(u32 method, u32 method_argument, bool is_last_call) override;
@@ -149,7 +152,7 @@ public:
149 }; 152 };
150 153
151private: 154private:
152 VideoCore::RasterizerInterface& rasterizer; 155 VideoCore::RasterizerInterface* rasterizer;
153 156
154 /// Performs the copy from the source surface to the destination surface as configured in the 157 /// Performs the copy from the source surface to the destination surface as configured in the
155 /// registers. 158 /// registers.
diff --git a/src/video_core/engines/kepler_compute.cpp b/src/video_core/engines/kepler_compute.cpp
index a82b06a38..898370739 100644
--- a/src/video_core/engines/kepler_compute.cpp
+++ b/src/video_core/engines/kepler_compute.cpp
@@ -16,14 +16,15 @@
16 16
17namespace Tegra::Engines { 17namespace Tegra::Engines {
18 18
19KeplerCompute::KeplerCompute(Core::System& system, VideoCore::RasterizerInterface& rasterizer, 19KeplerCompute::KeplerCompute(Core::System& system_, MemoryManager& memory_manager_)
20 MemoryManager& memory_manager) 20 : system{system_}, memory_manager{memory_manager_}, upload_state{memory_manager, regs.upload} {}
21 : system{system}, rasterizer{rasterizer}, memory_manager{memory_manager}, upload_state{
22 memory_manager,
23 regs.upload} {}
24 21
25KeplerCompute::~KeplerCompute() = default; 22KeplerCompute::~KeplerCompute() = default;
26 23
24void KeplerCompute::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
25 rasterizer = &rasterizer_;
26}
27
27void KeplerCompute::CallMethod(u32 method, u32 method_argument, bool is_last_call) { 28void KeplerCompute::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
28 ASSERT_MSG(method < Regs::NUM_REGS, 29 ASSERT_MSG(method < Regs::NUM_REGS,
29 "Invalid KeplerCompute register, increase the size of the Regs structure"); 30 "Invalid KeplerCompute register, increase the size of the Regs structure");
@@ -104,11 +105,11 @@ SamplerDescriptor KeplerCompute::AccessSampler(u32 handle) const {
104} 105}
105 106
106VideoCore::GuestDriverProfile& KeplerCompute::AccessGuestDriverProfile() { 107VideoCore::GuestDriverProfile& KeplerCompute::AccessGuestDriverProfile() {
107 return rasterizer.AccessGuestDriverProfile(); 108 return rasterizer->AccessGuestDriverProfile();
108} 109}
109 110
110const VideoCore::GuestDriverProfile& KeplerCompute::AccessGuestDriverProfile() const { 111const VideoCore::GuestDriverProfile& KeplerCompute::AccessGuestDriverProfile() const {
111 return rasterizer.AccessGuestDriverProfile(); 112 return rasterizer->AccessGuestDriverProfile();
112} 113}
113 114
114void KeplerCompute::ProcessLaunch() { 115void KeplerCompute::ProcessLaunch() {
@@ -119,7 +120,7 @@ void KeplerCompute::ProcessLaunch() {
119 const GPUVAddr code_addr = regs.code_loc.Address() + launch_description.program_start; 120 const GPUVAddr code_addr = regs.code_loc.Address() + launch_description.program_start;
120 LOG_TRACE(HW_GPU, "Compute invocation launched at address 0x{:016x}", code_addr); 121 LOG_TRACE(HW_GPU, "Compute invocation launched at address 0x{:016x}", code_addr);
121 122
122 rasterizer.DispatchCompute(code_addr); 123 rasterizer->DispatchCompute(code_addr);
123} 124}
124 125
125Texture::TICEntry KeplerCompute::GetTICEntry(u32 tic_index) const { 126Texture::TICEntry KeplerCompute::GetTICEntry(u32 tic_index) const {
diff --git a/src/video_core/engines/kepler_compute.h b/src/video_core/engines/kepler_compute.h
index b7f668d88..7f2500aab 100644
--- a/src/video_core/engines/kepler_compute.h
+++ b/src/video_core/engines/kepler_compute.h
@@ -42,10 +42,12 @@ namespace Tegra::Engines {
42 42
43class KeplerCompute final : public ConstBufferEngineInterface, public EngineInterface { 43class KeplerCompute final : public ConstBufferEngineInterface, public EngineInterface {
44public: 44public:
45 explicit KeplerCompute(Core::System& system, VideoCore::RasterizerInterface& rasterizer, 45 explicit KeplerCompute(Core::System& system, MemoryManager& memory_manager);
46 MemoryManager& memory_manager);
47 ~KeplerCompute(); 46 ~KeplerCompute();
48 47
48 /// Binds a rasterizer to this engine.
49 void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
50
49 static constexpr std::size_t NumConstBuffers = 8; 51 static constexpr std::size_t NumConstBuffers = 8;
50 52
51 struct Regs { 53 struct Regs {
@@ -230,11 +232,6 @@ public:
230 const VideoCore::GuestDriverProfile& AccessGuestDriverProfile() const override; 232 const VideoCore::GuestDriverProfile& AccessGuestDriverProfile() const override;
231 233
232private: 234private:
233 Core::System& system;
234 VideoCore::RasterizerInterface& rasterizer;
235 MemoryManager& memory_manager;
236 Upload::State upload_state;
237
238 void ProcessLaunch(); 235 void ProcessLaunch();
239 236
240 /// Retrieves information about a specific TIC entry from the TIC buffer. 237 /// Retrieves information about a specific TIC entry from the TIC buffer.
@@ -242,6 +239,11 @@ private:
242 239
243 /// Retrieves information about a specific TSC entry from the TSC buffer. 240 /// Retrieves information about a specific TSC entry from the TSC buffer.
244 Texture::TSCEntry GetTSCEntry(u32 tsc_index) const; 241 Texture::TSCEntry GetTSCEntry(u32 tsc_index) const;
242
243 Core::System& system;
244 MemoryManager& memory_manager;
245 VideoCore::RasterizerInterface* rasterizer = nullptr;
246 Upload::State upload_state;
245}; 247};
246 248
247#define ASSERT_REG_POSITION(field_name, position) \ 249#define ASSERT_REG_POSITION(field_name, position) \
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index c01436295..33854445f 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -22,14 +22,19 @@ using VideoCore::QueryType;
22/// First register id that is actually a Macro call. 22/// First register id that is actually a Macro call.
23constexpr u32 MacroRegistersStart = 0xE00; 23constexpr u32 MacroRegistersStart = 0xE00;
24 24
25Maxwell3D::Maxwell3D(Core::System& system, VideoCore::RasterizerInterface& rasterizer, 25Maxwell3D::Maxwell3D(Core::System& system_, MemoryManager& memory_manager_)
26 MemoryManager& memory_manager) 26 : system{system_}, memory_manager{memory_manager_}, macro_engine{GetMacroEngine(*this)},
27 : system{system}, rasterizer{rasterizer}, memory_manager{memory_manager}, 27 upload_state{memory_manager, regs.upload} {
28 macro_engine{GetMacroEngine(*this)}, upload_state{memory_manager, regs.upload} {
29 dirty.flags.flip(); 28 dirty.flags.flip();
30 InitializeRegisterDefaults(); 29 InitializeRegisterDefaults();
31} 30}
32 31
32Maxwell3D::~Maxwell3D() = default;
33
34void Maxwell3D::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
35 rasterizer = &rasterizer_;
36}
37
33void Maxwell3D::InitializeRegisterDefaults() { 38void Maxwell3D::InitializeRegisterDefaults() {
34 // Initializes registers to their default values - what games expect them to be at boot. This is 39 // Initializes registers to their default values - what games expect them to be at boot. This is
35 // for certain registers that may not be explicitly set by games. 40 // for certain registers that may not be explicitly set by games.
@@ -192,7 +197,7 @@ void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
192 197
193 switch (method) { 198 switch (method) {
194 case MAXWELL3D_REG_INDEX(wait_for_idle): { 199 case MAXWELL3D_REG_INDEX(wait_for_idle): {
195 rasterizer.WaitForIdle(); 200 rasterizer->WaitForIdle();
196 break; 201 break;
197 } 202 }
198 case MAXWELL3D_REG_INDEX(shadow_ram_control): { 203 case MAXWELL3D_REG_INDEX(shadow_ram_control): {
@@ -402,7 +407,7 @@ void Maxwell3D::FlushMMEInlineDraw() {
402 407
403 const bool is_indexed = mme_draw.current_mode == MMEDrawMode::Indexed; 408 const bool is_indexed = mme_draw.current_mode == MMEDrawMode::Indexed;
404 if (ShouldExecute()) { 409 if (ShouldExecute()) {
405 rasterizer.Draw(is_indexed, true); 410 rasterizer->Draw(is_indexed, true);
406 } 411 }
407 412
408 // TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if 413 // TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if
@@ -465,7 +470,7 @@ void Maxwell3D::ProcessQueryGet() {
465 switch (regs.query.query_get.operation) { 470 switch (regs.query.query_get.operation) {
466 case Regs::QueryOperation::Release: 471 case Regs::QueryOperation::Release:
467 if (regs.query.query_get.fence == 1) { 472 if (regs.query.query_get.fence == 1) {
468 rasterizer.SignalSemaphore(regs.query.QueryAddress(), regs.query.query_sequence); 473 rasterizer->SignalSemaphore(regs.query.QueryAddress(), regs.query.query_sequence);
469 } else { 474 } else {
470 StampQueryResult(regs.query.query_sequence, regs.query.query_get.short_query == 0); 475 StampQueryResult(regs.query.query_sequence, regs.query.query_get.short_query == 0);
471 } 476 }
@@ -533,7 +538,7 @@ void Maxwell3D::ProcessQueryCondition() {
533void Maxwell3D::ProcessCounterReset() { 538void Maxwell3D::ProcessCounterReset() {
534 switch (regs.counter_reset) { 539 switch (regs.counter_reset) {
535 case Regs::CounterReset::SampleCnt: 540 case Regs::CounterReset::SampleCnt:
536 rasterizer.ResetCounter(QueryType::SamplesPassed); 541 rasterizer->ResetCounter(QueryType::SamplesPassed);
537 break; 542 break;
538 default: 543 default:
539 LOG_DEBUG(Render_OpenGL, "Unimplemented counter reset={}", 544 LOG_DEBUG(Render_OpenGL, "Unimplemented counter reset={}",
@@ -547,7 +552,7 @@ void Maxwell3D::ProcessSyncPoint() {
547 const u32 increment = regs.sync_info.increment.Value(); 552 const u32 increment = regs.sync_info.increment.Value();
548 [[maybe_unused]] const u32 cache_flush = regs.sync_info.unknown.Value(); 553 [[maybe_unused]] const u32 cache_flush = regs.sync_info.unknown.Value();
549 if (increment) { 554 if (increment) {
550 rasterizer.SignalSyncPoint(sync_point); 555 rasterizer->SignalSyncPoint(sync_point);
551 } 556 }
552} 557}
553 558
@@ -570,7 +575,7 @@ void Maxwell3D::DrawArrays() {
570 575
571 const bool is_indexed{regs.index_array.count && !regs.vertex_buffer.count}; 576 const bool is_indexed{regs.index_array.count && !regs.vertex_buffer.count};
572 if (ShouldExecute()) { 577 if (ShouldExecute()) {
573 rasterizer.Draw(is_indexed, false); 578 rasterizer->Draw(is_indexed, false);
574 } 579 }
575 580
576 // TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if 581 // TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if
@@ -590,8 +595,8 @@ std::optional<u64> Maxwell3D::GetQueryResult() {
590 return 0; 595 return 0;
591 case Regs::QuerySelect::SamplesPassed: 596 case Regs::QuerySelect::SamplesPassed:
592 // Deferred. 597 // Deferred.
593 rasterizer.Query(regs.query.QueryAddress(), VideoCore::QueryType::SamplesPassed, 598 rasterizer->Query(regs.query.QueryAddress(), VideoCore::QueryType::SamplesPassed,
594 system.GPU().GetTicks()); 599 system.GPU().GetTicks());
595 return {}; 600 return {};
596 default: 601 default:
597 LOG_DEBUG(HW_GPU, "Unimplemented query select type {}", 602 LOG_DEBUG(HW_GPU, "Unimplemented query select type {}",
@@ -718,7 +723,7 @@ void Maxwell3D::ProcessClearBuffers() {
718 regs.clear_buffers.R == regs.clear_buffers.B && 723 regs.clear_buffers.R == regs.clear_buffers.B &&
719 regs.clear_buffers.R == regs.clear_buffers.A); 724 regs.clear_buffers.R == regs.clear_buffers.A);
720 725
721 rasterizer.Clear(); 726 rasterizer->Clear();
722} 727}
723 728
724u32 Maxwell3D::AccessConstBuffer32(ShaderType stage, u64 const_buffer, u64 offset) const { 729u32 Maxwell3D::AccessConstBuffer32(ShaderType stage, u64 const_buffer, u64 offset) const {
@@ -752,11 +757,11 @@ SamplerDescriptor Maxwell3D::AccessSampler(u32 handle) const {
752} 757}
753 758
754VideoCore::GuestDriverProfile& Maxwell3D::AccessGuestDriverProfile() { 759VideoCore::GuestDriverProfile& Maxwell3D::AccessGuestDriverProfile() {
755 return rasterizer.AccessGuestDriverProfile(); 760 return rasterizer->AccessGuestDriverProfile();
756} 761}
757 762
758const VideoCore::GuestDriverProfile& Maxwell3D::AccessGuestDriverProfile() const { 763const VideoCore::GuestDriverProfile& Maxwell3D::AccessGuestDriverProfile() const {
759 return rasterizer.AccessGuestDriverProfile(); 764 return rasterizer->AccessGuestDriverProfile();
760} 765}
761 766
762} // namespace Tegra::Engines 767} // namespace Tegra::Engines
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index c97eeb792..bc289c55d 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -51,9 +51,11 @@ namespace Tegra::Engines {
51 51
52class Maxwell3D final : public ConstBufferEngineInterface, public EngineInterface { 52class Maxwell3D final : public ConstBufferEngineInterface, public EngineInterface {
53public: 53public:
54 explicit Maxwell3D(Core::System& system, VideoCore::RasterizerInterface& rasterizer, 54 explicit Maxwell3D(Core::System& system, MemoryManager& memory_manager);
55 MemoryManager& memory_manager); 55 ~Maxwell3D();
56 ~Maxwell3D() = default; 56
57 /// Binds a rasterizer to this engine.
58 void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
57 59
58 /// Register structure of the Maxwell3D engine. 60 /// Register structure of the Maxwell3D engine.
59 /// TODO(Subv): This structure will need to be made bigger as more registers are discovered. 61 /// TODO(Subv): This structure will need to be made bigger as more registers are discovered.
@@ -1418,12 +1420,12 @@ public:
1418 return execute_on; 1420 return execute_on;
1419 } 1421 }
1420 1422
1421 VideoCore::RasterizerInterface& GetRasterizer() { 1423 VideoCore::RasterizerInterface& Rasterizer() {
1422 return rasterizer; 1424 return *rasterizer;
1423 } 1425 }
1424 1426
1425 const VideoCore::RasterizerInterface& GetRasterizer() const { 1427 const VideoCore::RasterizerInterface& Rasterizer() const {
1426 return rasterizer; 1428 return *rasterizer;
1427 } 1429 }
1428 1430
1429 /// Notify a memory write has happened. 1431 /// Notify a memory write has happened.
@@ -1460,11 +1462,10 @@ private:
1460 void InitializeRegisterDefaults(); 1462 void InitializeRegisterDefaults();
1461 1463
1462 Core::System& system; 1464 Core::System& system;
1463
1464 VideoCore::RasterizerInterface& rasterizer;
1465
1466 MemoryManager& memory_manager; 1465 MemoryManager& memory_manager;
1467 1466
1467 VideoCore::RasterizerInterface* rasterizer = nullptr;
1468
1468 /// Start offsets of each macro in macro_memory 1469 /// Start offsets of each macro in macro_memory
1469 std::array<u32, 0x80> macro_positions = {}; 1470 std::array<u32, 0x80> macro_positions = {};
1470 1471
diff --git a/src/video_core/fence_manager.h b/src/video_core/fence_manager.h
index 8b2a6a42c..06cc12d5a 100644
--- a/src/video_core/fence_manager.h
+++ b/src/video_core/fence_manager.h
@@ -5,15 +5,10 @@
5#pragma once 5#pragma once
6 6
7#include <algorithm> 7#include <algorithm>
8#include <array>
9#include <memory>
10#include <queue> 8#include <queue>
11 9
12#include "common/assert.h"
13#include "common/common_types.h" 10#include "common/common_types.h"
14#include "core/core.h" 11#include "core/core.h"
15#include "core/memory.h"
16#include "core/settings.h"
17#include "video_core/gpu.h" 12#include "video_core/gpu.h"
18#include "video_core/memory_manager.h" 13#include "video_core/memory_manager.h"
19#include "video_core/rasterizer_interface.h" 14#include "video_core/rasterizer_interface.h"
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp
index 512578c8b..acb6e6d46 100644
--- a/src/video_core/gpu.cpp
+++ b/src/video_core/gpu.cpp
@@ -27,21 +27,28 @@ namespace Tegra {
27 27
28MICROPROFILE_DEFINE(GPU_wait, "GPU", "Wait for the GPU", MP_RGB(128, 128, 192)); 28MICROPROFILE_DEFINE(GPU_wait, "GPU", "Wait for the GPU", MP_RGB(128, 128, 192));
29 29
30GPU::GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer_, bool is_async) 30GPU::GPU(Core::System& system_, bool is_async_)
31 : system{system}, renderer{std::move(renderer_)}, is_async{is_async} { 31 : system{system_}, dma_pusher{std::make_unique<Tegra::DmaPusher>(system, *this)},
32 auto& rasterizer{renderer->Rasterizer()}; 32 memory_manager{std::make_unique<Tegra::MemoryManager>(system)},
33 memory_manager = std::make_unique<Tegra::MemoryManager>(system, rasterizer); 33 maxwell_3d{std::make_unique<Engines::Maxwell3D>(system, *memory_manager)},
34 dma_pusher = std::make_unique<Tegra::DmaPusher>(system, *this); 34 fermi_2d{std::make_unique<Engines::Fermi2D>()},
35 maxwell_3d = std::make_unique<Engines::Maxwell3D>(system, rasterizer, *memory_manager); 35 kepler_compute{std::make_unique<Engines::KeplerCompute>(system, *memory_manager)},
36 fermi_2d = std::make_unique<Engines::Fermi2D>(rasterizer); 36 maxwell_dma{std::make_unique<Engines::MaxwellDMA>(system, *memory_manager)},
37 kepler_compute = std::make_unique<Engines::KeplerCompute>(system, rasterizer, *memory_manager); 37 kepler_memory{std::make_unique<Engines::KeplerMemory>(system, *memory_manager)},
38 maxwell_dma = std::make_unique<Engines::MaxwellDMA>(system, *memory_manager); 38 shader_notify{std::make_unique<VideoCore::ShaderNotify>()}, is_async{is_async_} {}
39 kepler_memory = std::make_unique<Engines::KeplerMemory>(system, *memory_manager);
40 shader_notify = std::make_unique<VideoCore::ShaderNotify>();
41}
42 39
43GPU::~GPU() = default; 40GPU::~GPU() = default;
44 41
42void GPU::BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer_) {
43 renderer = std::move(renderer_);
44
45 VideoCore::RasterizerInterface& rasterizer = renderer->Rasterizer();
46 memory_manager->BindRasterizer(rasterizer);
47 maxwell_3d->BindRasterizer(rasterizer);
48 fermi_2d->BindRasterizer(rasterizer);
49 kepler_compute->BindRasterizer(rasterizer);
50}
51
45Engines::Maxwell3D& GPU::Maxwell3D() { 52Engines::Maxwell3D& GPU::Maxwell3D() {
46 return *maxwell_3d; 53 return *maxwell_3d;
47} 54}
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index ebfc7b0c7..c7d11deb2 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -142,11 +142,6 @@ class MemoryManager;
142 142
143class GPU { 143class GPU {
144public: 144public:
145 explicit GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer,
146 bool is_async);
147
148 virtual ~GPU();
149
150 struct MethodCall { 145 struct MethodCall {
151 u32 method{}; 146 u32 method{};
152 u32 argument{}; 147 u32 argument{};
@@ -162,6 +157,12 @@ public:
162 method_count(method_count) {} 157 method_count(method_count) {}
163 }; 158 };
164 159
160 explicit GPU(Core::System& system, bool is_async);
161 virtual ~GPU();
162
163 /// Binds a renderer to the GPU.
164 void BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer);
165
165 /// Calls a GPU method. 166 /// Calls a GPU method.
166 void CallMethod(const MethodCall& method_call); 167 void CallMethod(const MethodCall& method_call);
167 168
@@ -345,8 +346,8 @@ private:
345 bool ExecuteMethodOnEngine(u32 method); 346 bool ExecuteMethodOnEngine(u32 method);
346 347
347protected: 348protected:
348 std::unique_ptr<Tegra::DmaPusher> dma_pusher;
349 Core::System& system; 349 Core::System& system;
350 std::unique_ptr<Tegra::DmaPusher> dma_pusher;
350 std::unique_ptr<VideoCore::RendererBase> renderer; 351 std::unique_ptr<VideoCore::RendererBase> renderer;
351 352
352private: 353private:
diff --git a/src/video_core/gpu_asynch.cpp b/src/video_core/gpu_asynch.cpp
index 7b855f63e..70a3d5738 100644
--- a/src/video_core/gpu_asynch.cpp
+++ b/src/video_core/gpu_asynch.cpp
@@ -10,16 +10,14 @@
10 10
11namespace VideoCommon { 11namespace VideoCommon {
12 12
13GPUAsynch::GPUAsynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer_, 13GPUAsynch::GPUAsynch(Core::System& system) : GPU{system, true}, gpu_thread{system} {}
14 std::unique_ptr<Core::Frontend::GraphicsContext>&& context)
15 : GPU(system, std::move(renderer_), true), gpu_thread{system},
16 cpu_context(renderer->GetRenderWindow().CreateSharedContext()),
17 gpu_context(std::move(context)) {}
18 14
19GPUAsynch::~GPUAsynch() = default; 15GPUAsynch::~GPUAsynch() = default;
20 16
21void GPUAsynch::Start() { 17void GPUAsynch::Start() {
22 gpu_thread.StartThread(*renderer, *gpu_context, *dma_pusher); 18 gpu_thread.StartThread(*renderer, renderer->Context(), *dma_pusher);
19 cpu_context = renderer->GetRenderWindow().CreateSharedContext();
20 cpu_context->MakeCurrent();
23} 21}
24 22
25void GPUAsynch::ObtainContext() { 23void GPUAsynch::ObtainContext() {
diff --git a/src/video_core/gpu_asynch.h b/src/video_core/gpu_asynch.h
index 15e9f1d38..f89c855a5 100644
--- a/src/video_core/gpu_asynch.h
+++ b/src/video_core/gpu_asynch.h
@@ -20,8 +20,7 @@ namespace VideoCommon {
20/// Implementation of GPU interface that runs the GPU asynchronously 20/// Implementation of GPU interface that runs the GPU asynchronously
21class GPUAsynch final : public Tegra::GPU { 21class GPUAsynch final : public Tegra::GPU {
22public: 22public:
23 explicit GPUAsynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer, 23 explicit GPUAsynch(Core::System& system);
24 std::unique_ptr<Core::Frontend::GraphicsContext>&& context);
25 ~GPUAsynch() override; 24 ~GPUAsynch() override;
26 25
27 void Start() override; 26 void Start() override;
@@ -42,7 +41,6 @@ protected:
42private: 41private:
43 GPUThread::ThreadManager gpu_thread; 42 GPUThread::ThreadManager gpu_thread;
44 std::unique_ptr<Core::Frontend::GraphicsContext> cpu_context; 43 std::unique_ptr<Core::Frontend::GraphicsContext> cpu_context;
45 std::unique_ptr<Core::Frontend::GraphicsContext> gpu_context;
46}; 44};
47 45
48} // namespace VideoCommon 46} // namespace VideoCommon
diff --git a/src/video_core/gpu_synch.cpp b/src/video_core/gpu_synch.cpp
index aaeb9811d..1ca47ddef 100644
--- a/src/video_core/gpu_synch.cpp
+++ b/src/video_core/gpu_synch.cpp
@@ -7,20 +7,18 @@
7 7
8namespace VideoCommon { 8namespace VideoCommon {
9 9
10GPUSynch::GPUSynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer, 10GPUSynch::GPUSynch(Core::System& system) : GPU{system, false} {}
11 std::unique_ptr<Core::Frontend::GraphicsContext>&& context)
12 : GPU(system, std::move(renderer), false), context{std::move(context)} {}
13 11
14GPUSynch::~GPUSynch() = default; 12GPUSynch::~GPUSynch() = default;
15 13
16void GPUSynch::Start() {} 14void GPUSynch::Start() {}
17 15
18void GPUSynch::ObtainContext() { 16void GPUSynch::ObtainContext() {
19 context->MakeCurrent(); 17 renderer->Context().MakeCurrent();
20} 18}
21 19
22void GPUSynch::ReleaseContext() { 20void GPUSynch::ReleaseContext() {
23 context->DoneCurrent(); 21 renderer->Context().DoneCurrent();
24} 22}
25 23
26void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) { 24void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) {
diff --git a/src/video_core/gpu_synch.h b/src/video_core/gpu_synch.h
index 762c20aa5..297258cb1 100644
--- a/src/video_core/gpu_synch.h
+++ b/src/video_core/gpu_synch.h
@@ -19,8 +19,7 @@ namespace VideoCommon {
19/// Implementation of GPU interface that runs the GPU synchronously 19/// Implementation of GPU interface that runs the GPU synchronously
20class GPUSynch final : public Tegra::GPU { 20class GPUSynch final : public Tegra::GPU {
21public: 21public:
22 explicit GPUSynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer, 22 explicit GPUSynch(Core::System& system);
23 std::unique_ptr<Core::Frontend::GraphicsContext>&& context);
24 ~GPUSynch() override; 23 ~GPUSynch() override;
25 24
26 void Start() override; 25 void Start() override;
@@ -36,9 +35,6 @@ public:
36protected: 35protected:
37 void TriggerCpuInterrupt([[maybe_unused]] u32 syncpoint_id, 36 void TriggerCpuInterrupt([[maybe_unused]] u32 syncpoint_id,
38 [[maybe_unused]] u32 value) const override {} 37 [[maybe_unused]] u32 value) const override {}
39
40private:
41 std::unique_ptr<Core::Frontend::GraphicsContext> context;
42}; 38};
43 39
44} // namespace VideoCommon 40} // namespace VideoCommon
diff --git a/src/video_core/macro/macro_hle.cpp b/src/video_core/macro/macro_hle.cpp
index 0c9ff59a4..df00b57df 100644
--- a/src/video_core/macro/macro_hle.cpp
+++ b/src/video_core/macro/macro_hle.cpp
@@ -24,7 +24,7 @@ void HLE_771BB18C62444DA0(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
24 maxwell3d.regs.index_array.first = parameters[4]; 24 maxwell3d.regs.index_array.first = parameters[4];
25 25
26 if (maxwell3d.ShouldExecute()) { 26 if (maxwell3d.ShouldExecute()) {
27 maxwell3d.GetRasterizer().Draw(true, true); 27 maxwell3d.Rasterizer().Draw(true, true);
28 } 28 }
29 maxwell3d.regs.index_array.count = 0; 29 maxwell3d.regs.index_array.count = 0;
30 maxwell3d.mme_draw.instance_count = 0; 30 maxwell3d.mme_draw.instance_count = 0;
@@ -42,7 +42,7 @@ void HLE_0D61FC9FAAC9FCAD(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
42 maxwell3d.mme_draw.instance_count = count; 42 maxwell3d.mme_draw.instance_count = count;
43 43
44 if (maxwell3d.ShouldExecute()) { 44 if (maxwell3d.ShouldExecute()) {
45 maxwell3d.GetRasterizer().Draw(false, true); 45 maxwell3d.Rasterizer().Draw(false, true);
46 } 46 }
47 maxwell3d.regs.vertex_buffer.count = 0; 47 maxwell3d.regs.vertex_buffer.count = 0;
48 maxwell3d.mme_draw.instance_count = 0; 48 maxwell3d.mme_draw.instance_count = 0;
@@ -65,7 +65,7 @@ void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
65 maxwell3d.regs.draw.topology.Assign( 65 maxwell3d.regs.draw.topology.Assign(
66 static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0])); 66 static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0]));
67 if (maxwell3d.ShouldExecute()) { 67 if (maxwell3d.ShouldExecute()) {
68 maxwell3d.GetRasterizer().Draw(true, true); 68 maxwell3d.Rasterizer().Draw(true, true);
69 } 69 }
70 maxwell3d.regs.reg_array[0x446] = 0x0; // vertex id base? 70 maxwell3d.regs.reg_array[0x446] = 0x0; // vertex id base?
71 maxwell3d.regs.index_array.count = 0; 71 maxwell3d.regs.index_array.count = 0;
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp
index 844164645..c217f5bb2 100644
--- a/src/video_core/memory_manager.cpp
+++ b/src/video_core/memory_manager.cpp
@@ -14,11 +14,15 @@
14 14
15namespace Tegra { 15namespace Tegra {
16 16
17MemoryManager::MemoryManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer) 17MemoryManager::MemoryManager(Core::System& system_)
18 : system{system}, rasterizer{rasterizer}, page_table(page_table_size) {} 18 : system{system_}, page_table(page_table_size) {}
19 19
20MemoryManager::~MemoryManager() = default; 20MemoryManager::~MemoryManager() = default;
21 21
22void MemoryManager::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
23 rasterizer = &rasterizer_;
24}
25
22GPUVAddr MemoryManager::UpdateRange(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size) { 26GPUVAddr MemoryManager::UpdateRange(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size) {
23 u64 remaining_size{size}; 27 u64 remaining_size{size};
24 for (u64 offset{}; offset < size; offset += page_size) { 28 for (u64 offset{}; offset < size; offset += page_size) {
@@ -217,7 +221,7 @@ void MemoryManager::ReadBlock(GPUVAddr gpu_src_addr, void* dest_buffer, std::siz
217 221
218 // Flush must happen on the rasterizer interface, such that memory is always synchronous 222 // Flush must happen on the rasterizer interface, such that memory is always synchronous
219 // when it is read (even when in asynchronous GPU mode). Fixes Dead Cells title menu. 223 // when it is read (even when in asynchronous GPU mode). Fixes Dead Cells title menu.
220 rasterizer.FlushRegion(src_addr, copy_amount); 224 rasterizer->FlushRegion(src_addr, copy_amount);
221 system.Memory().ReadBlockUnsafe(src_addr, dest_buffer, copy_amount); 225 system.Memory().ReadBlockUnsafe(src_addr, dest_buffer, copy_amount);
222 } 226 }
223 227
@@ -266,7 +270,7 @@ void MemoryManager::WriteBlock(GPUVAddr gpu_dest_addr, const void* src_buffer, s
266 270
267 // Invalidate must happen on the rasterizer interface, such that memory is always 271 // Invalidate must happen on the rasterizer interface, such that memory is always
268 // synchronous when it is written (even when in asynchronous GPU mode). 272 // synchronous when it is written (even when in asynchronous GPU mode).
269 rasterizer.InvalidateRegion(dest_addr, copy_amount); 273 rasterizer->InvalidateRegion(dest_addr, copy_amount);
270 system.Memory().WriteBlockUnsafe(dest_addr, src_buffer, copy_amount); 274 system.Memory().WriteBlockUnsafe(dest_addr, src_buffer, copy_amount);
271 } 275 }
272 276
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h
index 681bd9588..8953fcb53 100644
--- a/src/video_core/memory_manager.h
+++ b/src/video_core/memory_manager.h
@@ -68,9 +68,12 @@ static_assert(sizeof(PageEntry) == 4, "PageEntry is too large");
68 68
69class MemoryManager final { 69class MemoryManager final {
70public: 70public:
71 explicit MemoryManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer); 71 explicit MemoryManager(Core::System& system);
72 ~MemoryManager(); 72 ~MemoryManager();
73 73
74 /// Binds a renderer to the memory manager.
75 void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
76
74 std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr) const; 77 std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr) const;
75 78
76 template <typename T> 79 template <typename T>
@@ -141,7 +144,7 @@ private:
141 144
142 Core::System& system; 145 Core::System& system;
143 146
144 VideoCore::RasterizerInterface& rasterizer; 147 VideoCore::RasterizerInterface* rasterizer = nullptr;
145 148
146 std::vector<PageEntry> page_table; 149 std::vector<PageEntry> page_table;
147}; 150};
diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp
index dfb06e87e..a93a1732c 100644
--- a/src/video_core/renderer_base.cpp
+++ b/src/video_core/renderer_base.cpp
@@ -9,7 +9,9 @@
9 9
10namespace VideoCore { 10namespace VideoCore {
11 11
12RendererBase::RendererBase(Core::Frontend::EmuWindow& window) : render_window{window} { 12RendererBase::RendererBase(Core::Frontend::EmuWindow& window_,
13 std::unique_ptr<Core::Frontend::GraphicsContext> context_)
14 : render_window{window_}, context{std::move(context_)} {
13 RefreshBaseSettings(); 15 RefreshBaseSettings();
14} 16}
15 17
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h
index 1d85219b6..649074acd 100644
--- a/src/video_core/renderer_base.h
+++ b/src/video_core/renderer_base.h
@@ -15,7 +15,8 @@
15 15
16namespace Core::Frontend { 16namespace Core::Frontend {
17class EmuWindow; 17class EmuWindow;
18} 18class GraphicsContext;
19} // namespace Core::Frontend
19 20
20namespace VideoCore { 21namespace VideoCore {
21 22
@@ -25,14 +26,15 @@ struct RendererSettings {
25 26
26 // Screenshot 27 // Screenshot
27 std::atomic<bool> screenshot_requested{false}; 28 std::atomic<bool> screenshot_requested{false};
28 void* screenshot_bits; 29 void* screenshot_bits{};
29 std::function<void()> screenshot_complete_callback; 30 std::function<void()> screenshot_complete_callback;
30 Layout::FramebufferLayout screenshot_framebuffer_layout; 31 Layout::FramebufferLayout screenshot_framebuffer_layout;
31}; 32};
32 33
33class RendererBase : NonCopyable { 34class RendererBase : NonCopyable {
34public: 35public:
35 explicit RendererBase(Core::Frontend::EmuWindow& window); 36 explicit RendererBase(Core::Frontend::EmuWindow& window,
37 std::unique_ptr<Core::Frontend::GraphicsContext> context);
36 virtual ~RendererBase(); 38 virtual ~RendererBase();
37 39
38 /// Initialize the renderer 40 /// Initialize the renderer
@@ -68,6 +70,14 @@ public:
68 return *rasterizer; 70 return *rasterizer;
69 } 71 }
70 72
73 Core::Frontend::GraphicsContext& Context() {
74 return *context;
75 }
76
77 const Core::Frontend::GraphicsContext& Context() const {
78 return *context;
79 }
80
71 Core::Frontend::EmuWindow& GetRenderWindow() { 81 Core::Frontend::EmuWindow& GetRenderWindow() {
72 return render_window; 82 return render_window;
73 } 83 }
@@ -94,6 +104,7 @@ public:
94protected: 104protected:
95 Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle. 105 Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle.
96 std::unique_ptr<RasterizerInterface> rasterizer; 106 std::unique_ptr<RasterizerInterface> rasterizer;
107 std::unique_ptr<Core::Frontend::GraphicsContext> context;
97 f32 m_current_fps = 0.0f; ///< Current framerate, should be set by the renderer 108 f32 m_current_fps = 0.0f; ///< Current framerate, should be set by the renderer
98 int m_current_frame = 0; ///< Current frame, should be set by the renderer 109 int m_current_frame = 0; ///< Current frame, should be set by the renderer
99 110
diff --git a/src/video_core/renderer_opengl/gl_fence_manager.cpp b/src/video_core/renderer_opengl/gl_fence_manager.cpp
index ec5421afa..3d2588dd2 100644
--- a/src/video_core/renderer_opengl/gl_fence_manager.cpp
+++ b/src/video_core/renderer_opengl/gl_fence_manager.cpp
@@ -4,16 +4,17 @@
4 4
5#include "common/assert.h" 5#include "common/assert.h"
6 6
7#include <glad/glad.h>
8
7#include "video_core/renderer_opengl/gl_buffer_cache.h" 9#include "video_core/renderer_opengl/gl_buffer_cache.h"
8#include "video_core/renderer_opengl/gl_fence_manager.h" 10#include "video_core/renderer_opengl/gl_fence_manager.h"
9 11
10namespace OpenGL { 12namespace OpenGL {
11 13
12GLInnerFence::GLInnerFence(u32 payload, bool is_stubbed) 14GLInnerFence::GLInnerFence(u32 payload, bool is_stubbed) : FenceBase(payload, is_stubbed) {}
13 : VideoCommon::FenceBase(payload, is_stubbed), sync_object{} {}
14 15
15GLInnerFence::GLInnerFence(GPUVAddr address, u32 payload, bool is_stubbed) 16GLInnerFence::GLInnerFence(GPUVAddr address, u32 payload, bool is_stubbed)
16 : VideoCommon::FenceBase(address, payload, is_stubbed), sync_object{} {} 17 : FenceBase(address, payload, is_stubbed) {}
17 18
18GLInnerFence::~GLInnerFence() = default; 19GLInnerFence::~GLInnerFence() = default;
19 20
diff --git a/src/video_core/renderer_opengl/gl_fence_manager.h b/src/video_core/renderer_opengl/gl_fence_manager.h
index c917b3343..1686cf5c8 100644
--- a/src/video_core/renderer_opengl/gl_fence_manager.h
+++ b/src/video_core/renderer_opengl/gl_fence_manager.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include <memory> 7#include <memory>
8#include <glad/glad.h>
9 8
10#include "common/common_types.h" 9#include "common/common_types.h"
11#include "video_core/fence_manager.h" 10#include "video_core/fence_manager.h"
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp
index 0a7bc9e2b..f403f388a 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp
@@ -403,7 +403,7 @@ void CachedSurface::DecorateSurfaceName() {
403 LabelGLObject(GL_TEXTURE, texture.handle, GetGpuAddr(), params.TargetName()); 403 LabelGLObject(GL_TEXTURE, texture.handle, GetGpuAddr(), params.TargetName());
404} 404}
405 405
406void CachedSurfaceView::DecorateViewName(GPUVAddr gpu_addr, std::string prefix) { 406void CachedSurfaceView::DecorateViewName(GPUVAddr gpu_addr, const std::string& prefix) {
407 LabelGLObject(GL_TEXTURE, main_view.handle, gpu_addr, prefix); 407 LabelGLObject(GL_TEXTURE, main_view.handle, gpu_addr, prefix);
408} 408}
409 409
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h
index bfc4ddf5d..de8f18489 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.h
+++ b/src/video_core/renderer_opengl/gl_texture_cache.h
@@ -90,7 +90,7 @@ public:
90 Tegra::Texture::SwizzleSource z_source, 90 Tegra::Texture::SwizzleSource z_source,
91 Tegra::Texture::SwizzleSource w_source); 91 Tegra::Texture::SwizzleSource w_source);
92 92
93 void DecorateViewName(GPUVAddr gpu_addr, std::string prefix); 93 void DecorateViewName(GPUVAddr gpu_addr, const std::string& prefix);
94 94
95 void MarkAsModified(u64 tick) { 95 void MarkAsModified(u64 tick) {
96 surface.MarkAsModified(true, tick); 96 surface.MarkAsModified(true, tick);
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 14bbc3a1c..c39663db7 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -313,10 +313,11 @@ public:
313 } 313 }
314}; 314};
315 315
316RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system, 316RendererOpenGL::RendererOpenGL(Core::System& system_, Core::Frontend::EmuWindow& emu_window_,
317 Core::Frontend::GraphicsContext& context) 317 Tegra::GPU& gpu_,
318 : RendererBase{emu_window}, emu_window{emu_window}, system{system}, context{context}, 318 std::unique_ptr<Core::Frontend::GraphicsContext> context_)
319 program_manager{device}, has_debug_tool{HasDebugTool()} {} 319 : RendererBase{emu_window_, std::move(context_)}, system{system_},
320 emu_window{emu_window_}, gpu{gpu_}, program_manager{device}, has_debug_tool{HasDebugTool()} {}
320 321
321RendererOpenGL::~RendererOpenGL() = default; 322RendererOpenGL::~RendererOpenGL() = default;
322 323
@@ -384,7 +385,7 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
384 if (has_debug_tool) { 385 if (has_debug_tool) {
385 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); 386 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
386 Present(0); 387 Present(0);
387 context.SwapBuffers(); 388 context->SwapBuffers();
388 } 389 }
389} 390}
390 391
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index 8b18d32e6..52ea76b7d 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -56,8 +56,9 @@ class FrameMailbox;
56 56
57class RendererOpenGL final : public VideoCore::RendererBase { 57class RendererOpenGL final : public VideoCore::RendererBase {
58public: 58public:
59 explicit RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system, 59 explicit RendererOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window,
60 Core::Frontend::GraphicsContext& context); 60 Tegra::GPU& gpu,
61 std::unique_ptr<Core::Frontend::GraphicsContext> context);
61 ~RendererOpenGL() override; 62 ~RendererOpenGL() override;
62 63
63 bool Init() override; 64 bool Init() override;
@@ -93,9 +94,9 @@ private:
93 94
94 bool Present(int timeout_ms); 95 bool Present(int timeout_ms);
95 96
96 Core::Frontend::EmuWindow& emu_window;
97 Core::System& system; 97 Core::System& system;
98 Core::Frontend::GraphicsContext& context; 98 Core::Frontend::EmuWindow& emu_window;
99 Tegra::GPU& gpu;
99 const Device device; 100 const Device device;
100 101
101 StateTracker state_tracker{system}; 102 StateTracker state_tracker{system};
@@ -120,7 +121,7 @@ private:
120 std::vector<u8> gl_framebuffer_data; 121 std::vector<u8> gl_framebuffer_data;
121 122
122 /// Used for transforming the framebuffer orientation 123 /// Used for transforming the framebuffer orientation
123 Tegra::FramebufferConfig::TransformFlags framebuffer_transform_flags; 124 Tegra::FramebufferConfig::TransformFlags framebuffer_transform_flags{};
124 Common::Rectangle<int> framebuffer_crop_rect; 125 Common::Rectangle<int> framebuffer_crop_rect;
125 126
126 /// Frame presentation mailbox 127 /// Frame presentation mailbox
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
index 6e49699d0..ae46e0444 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
@@ -237,8 +237,10 @@ std::string BuildCommaSeparatedExtensions(std::vector<std::string> available_ext
237 237
238} // Anonymous namespace 238} // Anonymous namespace
239 239
240RendererVulkan::RendererVulkan(Core::Frontend::EmuWindow& window, Core::System& system) 240RendererVulkan::RendererVulkan(Core::System& system_, Core::Frontend::EmuWindow& emu_window,
241 : RendererBase(window), system{system} {} 241 Tegra::GPU& gpu_,
242 std::unique_ptr<Core::Frontend::GraphicsContext> context)
243 : RendererBase{emu_window, std::move(context)}, system{system_}, gpu{gpu_} {}
242 244
243RendererVulkan::~RendererVulkan() { 245RendererVulkan::~RendererVulkan() {
244 ShutDown(); 246 ShutDown();
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h
index 522b5bff8..13debbbc0 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.h
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.h
@@ -38,7 +38,9 @@ struct VKScreenInfo {
38 38
39class RendererVulkan final : public VideoCore::RendererBase { 39class RendererVulkan final : public VideoCore::RendererBase {
40public: 40public:
41 explicit RendererVulkan(Core::Frontend::EmuWindow& window, Core::System& system); 41 explicit RendererVulkan(Core::System& system, Core::Frontend::EmuWindow& emu_window,
42 Tegra::GPU& gpu,
43 std::unique_ptr<Core::Frontend::GraphicsContext> context);
42 ~RendererVulkan() override; 44 ~RendererVulkan() override;
43 45
44 bool Init() override; 46 bool Init() override;
@@ -58,6 +60,7 @@ private:
58 void Report() const; 60 void Report() const;
59 61
60 Core::System& system; 62 Core::System& system;
63 Tegra::GPU& gpu;
61 64
62 Common::DynamicLibrary library; 65 Common::DynamicLibrary library;
63 vk::InstanceDispatch dld; 66 vk::InstanceDispatch dld;
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp
index 45f360bdd..4e3a092c7 100644
--- a/src/video_core/video_core.cpp
+++ b/src/video_core/video_core.cpp
@@ -3,6 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <memory> 5#include <memory>
6
6#include "common/logging/log.h" 7#include "common/logging/log.h"
7#include "core/core.h" 8#include "core/core.h"
8#include "core/settings.h" 9#include "core/settings.h"
@@ -16,37 +17,46 @@
16#include "video_core/video_core.h" 17#include "video_core/video_core.h"
17 18
18namespace { 19namespace {
19std::unique_ptr<VideoCore::RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window, 20
20 Core::System& system, 21std::unique_ptr<VideoCore::RendererBase> CreateRenderer(
21 Core::Frontend::GraphicsContext& context) { 22 Core::System& system, Core::Frontend::EmuWindow& emu_window, Tegra::GPU& gpu,
23 std::unique_ptr<Core::Frontend::GraphicsContext> context) {
22 switch (Settings::values.renderer_backend.GetValue()) { 24 switch (Settings::values.renderer_backend.GetValue()) {
23 case Settings::RendererBackend::OpenGL: 25 case Settings::RendererBackend::OpenGL:
24 return std::make_unique<OpenGL::RendererOpenGL>(emu_window, system, context); 26 return std::make_unique<OpenGL::RendererOpenGL>(system, emu_window, gpu,
27 std::move(context));
25#ifdef HAS_VULKAN 28#ifdef HAS_VULKAN
26 case Settings::RendererBackend::Vulkan: 29 case Settings::RendererBackend::Vulkan:
27 return std::make_unique<Vulkan::RendererVulkan>(emu_window, system); 30 return std::make_unique<Vulkan::RendererVulkan>(system, emu_window, gpu,
31 std::move(context));
28#endif 32#endif
29 default: 33 default:
30 return nullptr; 34 return nullptr;
31 } 35 }
32} 36}
37
33} // Anonymous namespace 38} // Anonymous namespace
34 39
35namespace VideoCore { 40namespace VideoCore {
36 41
37std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system) { 42std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system) {
43 std::unique_ptr<Tegra::GPU> gpu;
44 if (Settings::values.use_asynchronous_gpu_emulation.GetValue()) {
45 gpu = std::make_unique<VideoCommon::GPUAsynch>(system);
46 } else {
47 gpu = std::make_unique<VideoCommon::GPUSynch>(system);
48 }
49
38 auto context = emu_window.CreateSharedContext(); 50 auto context = emu_window.CreateSharedContext();
39 const auto scope = context->Acquire(); 51 const auto scope = context->Acquire();
40 auto renderer = CreateRenderer(emu_window, system, *context); 52
53 auto renderer = CreateRenderer(system, emu_window, *gpu, std::move(context));
41 if (!renderer->Init()) { 54 if (!renderer->Init()) {
42 return nullptr; 55 return nullptr;
43 } 56 }
44 57
45 if (Settings::values.use_asynchronous_gpu_emulation.GetValue()) { 58 gpu->BindRenderer(std::move(renderer));
46 return std::make_unique<VideoCommon::GPUAsynch>(system, std::move(renderer), 59 return gpu;
47 std::move(context));
48 }
49 return std::make_unique<VideoCommon::GPUSynch>(system, std::move(renderer), std::move(context));
50} 60}
51 61
52u16 GetResolutionScaleFactor(const RendererBase& renderer) { 62u16 GetResolutionScaleFactor(const RendererBase& renderer) {