summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/engines/fermi_2d.cpp4
-rw-r--r--src/video_core/engines/fermi_2d.h2
-rw-r--r--src/video_core/engines/kepler_compute.cpp4
-rw-r--r--src/video_core/engines/kepler_compute.h2
-rw-r--r--src/video_core/engines/maxwell_3d.cpp4
-rw-r--r--src/video_core/engines/maxwell_3d.h2
-rw-r--r--src/video_core/gpu.cpp8
-rw-r--r--src/video_core/gpu.h1
-rw-r--r--src/video_core/gpu_thread.cpp12
-rw-r--r--src/video_core/gpu_thread.h8
-rw-r--r--src/video_core/memory_manager.cpp4
-rw-r--r--src/video_core/memory_manager.h2
-rw-r--r--src/video_core/renderer_base.h17
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp48
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.h11
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.cpp153
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.h43
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.cpp11
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.h15
-rw-r--r--src/video_core/renderer_vulkan/vk_swapchain.cpp7
-rw-r--r--src/video_core/renderer_vulkan/vk_swapchain.h3
-rw-r--r--src/video_core/video_core.cpp19
-rw-r--r--src/video_core/vulkan_common/vulkan_device.h2
-rw-r--r--src/video_core/vulkan_common/vulkan_wrapper.h3
-rw-r--r--src/yuzu/bootmanager.cpp2
-rw-r--r--src/yuzu/configuration/configure_graphics.cpp19
-rw-r--r--src/yuzu_cmd/yuzu.cpp2
27 files changed, 176 insertions, 232 deletions
diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp
index a01d334ad..0f640fdae 100644
--- a/src/video_core/engines/fermi_2d.cpp
+++ b/src/video_core/engines/fermi_2d.cpp
@@ -18,8 +18,8 @@ Fermi2D::Fermi2D() {
18 18
19Fermi2D::~Fermi2D() = default; 19Fermi2D::~Fermi2D() = default;
20 20
21void Fermi2D::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) { 21void Fermi2D::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) {
22 rasterizer = &rasterizer_; 22 rasterizer = rasterizer_;
23} 23}
24 24
25void Fermi2D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { 25void Fermi2D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
diff --git a/src/video_core/engines/fermi_2d.h b/src/video_core/engines/fermi_2d.h
index 0de3280a2..c808a577d 100644
--- a/src/video_core/engines/fermi_2d.h
+++ b/src/video_core/engines/fermi_2d.h
@@ -38,7 +38,7 @@ public:
38 ~Fermi2D(); 38 ~Fermi2D();
39 39
40 /// Binds a rasterizer to this engine. 40 /// Binds a rasterizer to this engine.
41 void BindRasterizer(VideoCore::RasterizerInterface& rasterizer); 41 void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
42 42
43 /// Write the value to the register identified by method. 43 /// Write the value to the register identified by method.
44 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;
diff --git a/src/video_core/engines/kepler_compute.cpp b/src/video_core/engines/kepler_compute.cpp
index ba387506e..ed29fc7ac 100644
--- a/src/video_core/engines/kepler_compute.cpp
+++ b/src/video_core/engines/kepler_compute.cpp
@@ -21,8 +21,8 @@ KeplerCompute::KeplerCompute(Core::System& system_, MemoryManager& memory_manage
21 21
22KeplerCompute::~KeplerCompute() = default; 22KeplerCompute::~KeplerCompute() = default;
23 23
24void KeplerCompute::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) { 24void KeplerCompute::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) {
25 rasterizer = &rasterizer_; 25 rasterizer = rasterizer_;
26} 26}
27 27
28void KeplerCompute::CallMethod(u32 method, u32 method_argument, bool is_last_call) { 28void KeplerCompute::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
diff --git a/src/video_core/engines/kepler_compute.h b/src/video_core/engines/kepler_compute.h
index 9f0a7b76d..7c40cba38 100644
--- a/src/video_core/engines/kepler_compute.h
+++ b/src/video_core/engines/kepler_compute.h
@@ -46,7 +46,7 @@ public:
46 ~KeplerCompute(); 46 ~KeplerCompute();
47 47
48 /// Binds a rasterizer to this engine. 48 /// Binds a rasterizer to this engine.
49 void BindRasterizer(VideoCore::RasterizerInterface& rasterizer); 49 void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
50 50
51 static constexpr std::size_t NumConstBuffers = 8; 51 static constexpr std::size_t NumConstBuffers = 8;
52 52
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index 116ad1722..d6ba9da5c 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -30,8 +30,8 @@ Maxwell3D::Maxwell3D(Core::System& system_, MemoryManager& memory_manager_)
30 30
31Maxwell3D::~Maxwell3D() = default; 31Maxwell3D::~Maxwell3D() = default;
32 32
33void Maxwell3D::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) { 33void Maxwell3D::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) {
34 rasterizer = &rasterizer_; 34 rasterizer = rasterizer_;
35} 35}
36 36
37void Maxwell3D::InitializeRegisterDefaults() { 37void Maxwell3D::InitializeRegisterDefaults() {
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 002d1b3f9..cc94d2678 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -55,7 +55,7 @@ public:
55 ~Maxwell3D(); 55 ~Maxwell3D();
56 56
57 /// Binds a rasterizer to this engine. 57 /// Binds a rasterizer to this engine.
58 void BindRasterizer(VideoCore::RasterizerInterface& rasterizer); 58 void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
59 59
60 /// Register structure of the Maxwell3D engine. 60 /// Register structure of the Maxwell3D engine.
61 /// 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.
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp
index 6ab06775f..2a9bd4121 100644
--- a/src/video_core/gpu.cpp
+++ b/src/video_core/gpu.cpp
@@ -44,8 +44,8 @@ GPU::~GPU() = default;
44 44
45void GPU::BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer_) { 45void GPU::BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer_) {
46 renderer = std::move(renderer_); 46 renderer = std::move(renderer_);
47 rasterizer = renderer->ReadRasterizer();
47 48
48 VideoCore::RasterizerInterface& rasterizer = renderer->Rasterizer();
49 memory_manager->BindRasterizer(rasterizer); 49 memory_manager->BindRasterizer(rasterizer);
50 maxwell_3d->BindRasterizer(rasterizer); 50 maxwell_3d->BindRasterizer(rasterizer);
51 fermi_2d->BindRasterizer(rasterizer); 51 fermi_2d->BindRasterizer(rasterizer);
@@ -171,7 +171,7 @@ void GPU::TickWork() {
171 const std::size_t size = request.size; 171 const std::size_t size = request.size;
172 flush_requests.pop_front(); 172 flush_requests.pop_front();
173 flush_request_mutex.unlock(); 173 flush_request_mutex.unlock();
174 renderer->Rasterizer().FlushRegion(addr, size); 174 rasterizer->FlushRegion(addr, size);
175 current_flush_fence.store(fence); 175 current_flush_fence.store(fence);
176 flush_request_mutex.lock(); 176 flush_request_mutex.lock();
177 } 177 }
@@ -193,11 +193,11 @@ u64 GPU::GetTicks() const {
193} 193}
194 194
195void GPU::FlushCommands() { 195void GPU::FlushCommands() {
196 renderer->Rasterizer().FlushCommands(); 196 rasterizer->FlushCommands();
197} 197}
198 198
199void GPU::SyncGuestHost() { 199void GPU::SyncGuestHost() {
200 renderer->Rasterizer().SyncGuestHost(); 200 rasterizer->SyncGuestHost();
201} 201}
202 202
203enum class GpuSemaphoreOperation { 203enum class GpuSemaphoreOperation {
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index b4ce6b154..b2ee45496 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -366,6 +366,7 @@ protected:
366 std::unique_ptr<Tegra::DmaPusher> dma_pusher; 366 std::unique_ptr<Tegra::DmaPusher> dma_pusher;
367 std::unique_ptr<Tegra::CDmaPusher> cdma_pusher; 367 std::unique_ptr<Tegra::CDmaPusher> cdma_pusher;
368 std::unique_ptr<VideoCore::RendererBase> renderer; 368 std::unique_ptr<VideoCore::RendererBase> renderer;
369 VideoCore::RasterizerInterface* rasterizer = nullptr;
369 const bool use_nvdec; 370 const bool use_nvdec;
370 371
371private: 372private:
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp
index 7e490bcc3..50319f1d5 100644
--- a/src/video_core/gpu_thread.cpp
+++ b/src/video_core/gpu_thread.cpp
@@ -38,6 +38,7 @@ static void RunThread(Core::System& system, VideoCore::RendererBase& renderer,
38 } 38 }
39 39
40 auto current_context = context.Acquire(); 40 auto current_context = context.Acquire();
41 VideoCore::RasterizerInterface* const rasterizer = renderer.ReadRasterizer();
41 42
42 CommandDataContainer next; 43 CommandDataContainer next;
43 while (state.is_running) { 44 while (state.is_running) {
@@ -52,13 +53,13 @@ static void RunThread(Core::System& system, VideoCore::RendererBase& renderer,
52 } else if (const auto* data = std::get_if<SwapBuffersCommand>(&next.data)) { 53 } else if (const auto* data = std::get_if<SwapBuffersCommand>(&next.data)) {
53 renderer.SwapBuffers(data->framebuffer ? &*data->framebuffer : nullptr); 54 renderer.SwapBuffers(data->framebuffer ? &*data->framebuffer : nullptr);
54 } else if (std::holds_alternative<OnCommandListEndCommand>(next.data)) { 55 } else if (std::holds_alternative<OnCommandListEndCommand>(next.data)) {
55 renderer.Rasterizer().ReleaseFences(); 56 rasterizer->ReleaseFences();
56 } else if (std::holds_alternative<GPUTickCommand>(next.data)) { 57 } else if (std::holds_alternative<GPUTickCommand>(next.data)) {
57 system.GPU().TickWork(); 58 system.GPU().TickWork();
58 } else if (const auto* flush = std::get_if<FlushRegionCommand>(&next.data)) { 59 } else if (const auto* flush = std::get_if<FlushRegionCommand>(&next.data)) {
59 renderer.Rasterizer().FlushRegion(flush->addr, flush->size); 60 rasterizer->FlushRegion(flush->addr, flush->size);
60 } else if (const auto* invalidate = std::get_if<InvalidateRegionCommand>(&next.data)) { 61 } else if (const auto* invalidate = std::get_if<InvalidateRegionCommand>(&next.data)) {
61 renderer.Rasterizer().OnCPUWrite(invalidate->addr, invalidate->size); 62 rasterizer->OnCPUWrite(invalidate->addr, invalidate->size);
62 } else if (std::holds_alternative<EndProcessingCommand>(next.data)) { 63 } else if (std::holds_alternative<EndProcessingCommand>(next.data)) {
63 return; 64 return;
64 } else { 65 } else {
@@ -84,6 +85,7 @@ ThreadManager::~ThreadManager() {
84void ThreadManager::StartThread(VideoCore::RendererBase& renderer, 85void ThreadManager::StartThread(VideoCore::RendererBase& renderer,
85 Core::Frontend::GraphicsContext& context, 86 Core::Frontend::GraphicsContext& context,
86 Tegra::DmaPusher& dma_pusher, Tegra::CDmaPusher& cdma_pusher) { 87 Tegra::DmaPusher& dma_pusher, Tegra::CDmaPusher& cdma_pusher) {
88 rasterizer = renderer.ReadRasterizer();
87 thread = std::thread(RunThread, std::ref(system), std::ref(renderer), std::ref(context), 89 thread = std::thread(RunThread, std::ref(system), std::ref(renderer), std::ref(context),
88 std::ref(dma_pusher), std::ref(state), std::ref(cdma_pusher)); 90 std::ref(dma_pusher), std::ref(state), std::ref(cdma_pusher));
89} 91}
@@ -129,12 +131,12 @@ void ThreadManager::FlushRegion(VAddr addr, u64 size) {
129} 131}
130 132
131void ThreadManager::InvalidateRegion(VAddr addr, u64 size) { 133void ThreadManager::InvalidateRegion(VAddr addr, u64 size) {
132 system.Renderer().Rasterizer().OnCPUWrite(addr, size); 134 rasterizer->OnCPUWrite(addr, size);
133} 135}
134 136
135void ThreadManager::FlushAndInvalidateRegion(VAddr addr, u64 size) { 137void ThreadManager::FlushAndInvalidateRegion(VAddr addr, u64 size) {
136 // Skip flush on asynch mode, as FlushAndInvalidateRegion is not used for anything too important 138 // Skip flush on asynch mode, as FlushAndInvalidateRegion is not used for anything too important
137 system.Renderer().Rasterizer().OnCPUWrite(addr, size); 139 rasterizer->OnCPUWrite(addr, size);
138} 140}
139 141
140void ThreadManager::WaitIdle() const { 142void ThreadManager::WaitIdle() const {
diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h
index 2775629e7..4cd951169 100644
--- a/src/video_core/gpu_thread.h
+++ b/src/video_core/gpu_thread.h
@@ -27,6 +27,7 @@ class System;
27} // namespace Core 27} // namespace Core
28 28
29namespace VideoCore { 29namespace VideoCore {
30class RasterizerInterface;
30class RendererBase; 31class RendererBase;
31} // namespace VideoCore 32} // namespace VideoCore
32 33
@@ -151,11 +152,12 @@ private:
151 /// Pushes a command to be executed by the GPU thread 152 /// Pushes a command to be executed by the GPU thread
152 u64 PushCommand(CommandData&& command_data); 153 u64 PushCommand(CommandData&& command_data);
153 154
154 SynchState state;
155 Core::System& system; 155 Core::System& system;
156 std::thread thread;
157 std::thread::id thread_id;
158 const bool is_async; 156 const bool is_async;
157 VideoCore::RasterizerInterface* rasterizer = nullptr;
158
159 SynchState state;
160 std::thread thread;
159}; 161};
160 162
161} // namespace VideoCommon::GPUThread 163} // namespace VideoCommon::GPUThread
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp
index c841f3cd7..44240a9c4 100644
--- a/src/video_core/memory_manager.cpp
+++ b/src/video_core/memory_manager.cpp
@@ -21,8 +21,8 @@ MemoryManager::MemoryManager(Core::System& system_)
21 21
22MemoryManager::~MemoryManager() = default; 22MemoryManager::~MemoryManager() = default;
23 23
24void MemoryManager::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) { 24void MemoryManager::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) {
25 rasterizer = &rasterizer_; 25 rasterizer = rasterizer_;
26} 26}
27 27
28GPUVAddr MemoryManager::UpdateRange(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size) { 28GPUVAddr MemoryManager::UpdateRange(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size) {
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h
index b468a67de..5d963eba6 100644
--- a/src/video_core/memory_manager.h
+++ b/src/video_core/memory_manager.h
@@ -72,7 +72,7 @@ public:
72 ~MemoryManager(); 72 ~MemoryManager();
73 73
74 /// Binds a renderer to the memory manager. 74 /// Binds a renderer to the memory manager.
75 void BindRasterizer(VideoCore::RasterizerInterface& rasterizer); 75 void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
76 76
77 [[nodiscard]] std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr) const; 77 [[nodiscard]] std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr) const;
78 78
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h
index 51dde8eb5..320ee8d30 100644
--- a/src/video_core/renderer_base.h
+++ b/src/video_core/renderer_base.h
@@ -37,15 +37,11 @@ public:
37 std::unique_ptr<Core::Frontend::GraphicsContext> context); 37 std::unique_ptr<Core::Frontend::GraphicsContext> context);
38 virtual ~RendererBase(); 38 virtual ~RendererBase();
39 39
40 /// Initialize the renderer
41 [[nodiscard]] virtual bool Init() = 0;
42
43 /// Shutdown the renderer
44 virtual void ShutDown() = 0;
45
46 /// Finalize rendering the guest frame and draw into the presentation texture 40 /// Finalize rendering the guest frame and draw into the presentation texture
47 virtual void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) = 0; 41 virtual void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) = 0;
48 42
43 [[nodiscard]] virtual RasterizerInterface* ReadRasterizer() = 0;
44
49 // Getter/setter functions: 45 // Getter/setter functions:
50 // ------------------------ 46 // ------------------------
51 47
@@ -57,14 +53,6 @@ public:
57 return m_current_frame; 53 return m_current_frame;
58 } 54 }
59 55
60 [[nodiscard]] RasterizerInterface& Rasterizer() {
61 return *rasterizer;
62 }
63
64 [[nodiscard]] const RasterizerInterface& Rasterizer() const {
65 return *rasterizer;
66 }
67
68 [[nodiscard]] Core::Frontend::GraphicsContext& Context() { 56 [[nodiscard]] Core::Frontend::GraphicsContext& Context() {
69 return *context; 57 return *context;
70 } 58 }
@@ -98,7 +86,6 @@ public:
98 86
99protected: 87protected:
100 Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle. 88 Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle.
101 std::unique_ptr<RasterizerInterface> rasterizer;
102 std::unique_ptr<Core::Frontend::GraphicsContext> context; 89 std::unique_ptr<Core::Frontend::GraphicsContext> context;
103 f32 m_current_fps = 0.0f; ///< Current framerate, should be set by the renderer 90 f32 m_current_fps = 0.0f; ///< Current framerate, should be set by the renderer
104 int m_current_frame = 0; ///< Current frame, should be set by the renderer 91 int m_current_frame = 0; ///< Current frame, should be set by the renderer
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 21159e498..7eb5ab17a 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -132,7 +132,20 @@ RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_,
132 Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_, 132 Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_,
133 std::unique_ptr<Core::Frontend::GraphicsContext> context_) 133 std::unique_ptr<Core::Frontend::GraphicsContext> context_)
134 : RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_}, 134 : RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_},
135 emu_window{emu_window_}, cpu_memory{cpu_memory_}, gpu{gpu_}, program_manager{device} {} 135 emu_window{emu_window_}, cpu_memory{cpu_memory_}, gpu{gpu_}, program_manager{device},
136 rasterizer{emu_window, gpu, cpu_memory, device, screen_info, program_manager, state_tracker} {
137 if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) {
138 glEnable(GL_DEBUG_OUTPUT);
139 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
140 glDebugMessageCallback(DebugHandler, nullptr);
141 }
142 AddTelemetryFields();
143
144 if (!GLAD_GL_VERSION_4_6) {
145 throw std::runtime_error{"OpenGL 4.3 is not available"};
146 }
147 InitOpenGLObjects();
148}
136 149
137RendererOpenGL::~RendererOpenGL() = default; 150RendererOpenGL::~RendererOpenGL() = default;
138 151
@@ -148,7 +161,7 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
148 161
149 ++m_current_frame; 162 ++m_current_frame;
150 163
151 rasterizer->TickFrame(); 164 rasterizer.TickFrame();
152 165
153 context->SwapBuffers(); 166 context->SwapBuffers();
154 render_window.OnFrameDisplayed(); 167 render_window.OnFrameDisplayed();
@@ -179,7 +192,7 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf
179 framebuffer_crop_rect = framebuffer.crop_rect; 192 framebuffer_crop_rect = framebuffer.crop_rect;
180 193
181 const VAddr framebuffer_addr{framebuffer.address + framebuffer.offset}; 194 const VAddr framebuffer_addr{framebuffer.address + framebuffer.offset};
182 if (rasterizer->AccelerateDisplay(framebuffer, framebuffer_addr, framebuffer.stride)) { 195 if (rasterizer.AccelerateDisplay(framebuffer, framebuffer_addr, framebuffer.stride)) {
183 return; 196 return;
184 } 197 }
185 198
@@ -289,14 +302,6 @@ void RendererOpenGL::AddTelemetryFields() {
289 telemetry_session.AddField(user_system, "GPU_OpenGL_Version", std::string(gl_version)); 302 telemetry_session.AddField(user_system, "GPU_OpenGL_Version", std::string(gl_version));
290} 303}
291 304
292void RendererOpenGL::CreateRasterizer() {
293 if (rasterizer) {
294 return;
295 }
296 rasterizer = std::make_unique<RasterizerOpenGL>(emu_window, gpu, cpu_memory, device,
297 screen_info, program_manager, state_tracker);
298}
299
300void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, 305void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
301 const Tegra::FramebufferConfig& framebuffer) { 306 const Tegra::FramebufferConfig& framebuffer) {
302 texture.width = framebuffer.width; 307 texture.width = framebuffer.width;
@@ -497,25 +502,4 @@ void RendererOpenGL::RenderScreenshot() {
497 renderer_settings.screenshot_requested = false; 502 renderer_settings.screenshot_requested = false;
498} 503}
499 504
500bool RendererOpenGL::Init() {
501 if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) {
502 glEnable(GL_DEBUG_OUTPUT);
503 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
504 glDebugMessageCallback(DebugHandler, nullptr);
505 }
506
507 AddTelemetryFields();
508
509 if (!GLAD_GL_VERSION_4_6) {
510 return false;
511 }
512
513 InitOpenGLObjects();
514 CreateRasterizer();
515
516 return true;
517}
518
519void RendererOpenGL::ShutDown() {}
520
521} // namespace OpenGL 505} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index 44e109794..e043a0ccb 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -10,6 +10,7 @@
10#include "common/math_util.h" 10#include "common/math_util.h"
11#include "video_core/renderer_base.h" 11#include "video_core/renderer_base.h"
12#include "video_core/renderer_opengl/gl_device.h" 12#include "video_core/renderer_opengl/gl_device.h"
13#include "video_core/renderer_opengl/gl_rasterizer.h"
13#include "video_core/renderer_opengl/gl_resource_manager.h" 14#include "video_core/renderer_opengl/gl_resource_manager.h"
14#include "video_core/renderer_opengl/gl_shader_manager.h" 15#include "video_core/renderer_opengl/gl_shader_manager.h"
15#include "video_core/renderer_opengl/gl_state_tracker.h" 16#include "video_core/renderer_opengl/gl_state_tracker.h"
@@ -63,18 +64,18 @@ public:
63 std::unique_ptr<Core::Frontend::GraphicsContext> context_); 64 std::unique_ptr<Core::Frontend::GraphicsContext> context_);
64 ~RendererOpenGL() override; 65 ~RendererOpenGL() override;
65 66
66 bool Init() override;
67 void ShutDown() override;
68 void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override; 67 void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override;
69 68
69 VideoCore::RasterizerInterface* ReadRasterizer() override {
70 return &rasterizer;
71 }
72
70private: 73private:
71 /// Initializes the OpenGL state and creates persistent objects. 74 /// Initializes the OpenGL state and creates persistent objects.
72 void InitOpenGLObjects(); 75 void InitOpenGLObjects();
73 76
74 void AddTelemetryFields(); 77 void AddTelemetryFields();
75 78
76 void CreateRasterizer();
77
78 void ConfigureFramebufferTexture(TextureInfo& texture, 79 void ConfigureFramebufferTexture(TextureInfo& texture,
79 const Tegra::FramebufferConfig& framebuffer); 80 const Tegra::FramebufferConfig& framebuffer);
80 81
@@ -118,6 +119,8 @@ private:
118 /// Global dummy shader pipeline 119 /// Global dummy shader pipeline
119 ProgramManager program_manager; 120 ProgramManager program_manager;
120 121
122 RasterizerOpenGL rasterizer;
123
121 /// OpenGL framebuffer data 124 /// OpenGL framebuffer data
122 std::vector<u8> gl_framebuffer_data; 125 std::vector<u8> gl_framebuffer_data;
123 126
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
index 61796e33a..6909576cb 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
@@ -80,17 +80,50 @@ std::string BuildCommaSeparatedExtensions(std::vector<std::string> available_ext
80 return separated_extensions; 80 return separated_extensions;
81} 81}
82 82
83Device CreateDevice(const vk::Instance& instance, const vk::InstanceDispatch& dld,
84 VkSurfaceKHR surface) {
85 const std::vector<VkPhysicalDevice> devices = instance.EnumeratePhysicalDevices();
86 const s32 device_index = Settings::values.vulkan_device.GetValue();
87 if (device_index < 0 || device_index >= static_cast<s32>(devices.size())) {
88 LOG_ERROR(Render_Vulkan, "Invalid device index {}!", device_index);
89 throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
90 }
91 const vk::PhysicalDevice physical_device(devices[device_index], dld);
92 return Device(*instance, physical_device, surface, dld);
93}
83} // Anonymous namespace 94} // Anonymous namespace
84 95
85RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_, 96RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_,
86 Core::Frontend::EmuWindow& emu_window, 97 Core::Frontend::EmuWindow& emu_window,
87 Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_, 98 Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_,
88 std::unique_ptr<Core::Frontend::GraphicsContext> context_) 99 std::unique_ptr<Core::Frontend::GraphicsContext> context_) try
89 : RendererBase{emu_window, std::move(context_)}, telemetry_session{telemetry_session_}, 100 : RendererBase(emu_window, std::move(context_)),
90 cpu_memory{cpu_memory_}, gpu{gpu_} {} 101 telemetry_session(telemetry_session_),
102 cpu_memory(cpu_memory_),
103 gpu(gpu_),
104 library(OpenLibrary()),
105 instance(CreateInstance(library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type,
106 true, Settings::values.renderer_debug)),
107 debug_callback(Settings::values.renderer_debug ? CreateDebugCallback(instance) : nullptr),
108 surface(CreateSurface(instance, render_window)),
109 device(CreateDevice(instance, dld, *surface)),
110 memory_allocator(device),
111 state_tracker(gpu),
112 scheduler(device, state_tracker),
113 swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width,
114 render_window.GetFramebufferLayout().height, false),
115 blit_screen(cpu_memory, render_window, device, memory_allocator, swapchain, scheduler,
116 screen_info),
117 rasterizer(render_window, gpu, gpu.MemoryManager(), cpu_memory, screen_info, device,
118 memory_allocator, state_tracker, scheduler) {
119 Report();
120} catch (const vk::Exception& exception) {
121 LOG_ERROR(Render_Vulkan, "Vulkan initialization failed with error: {}", exception.what());
122 throw std::runtime_error{fmt::format("Vulkan initialization error {}", exception.what())};
123}
91 124
92RendererVulkan::~RendererVulkan() { 125RendererVulkan::~RendererVulkan() {
93 ShutDown(); 126 void(device.GetLogical().WaitIdle());
94} 127}
95 128
96void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { 129void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
@@ -101,101 +134,38 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
101 if (layout.width > 0 && layout.height > 0 && render_window.IsShown()) { 134 if (layout.width > 0 && layout.height > 0 && render_window.IsShown()) {
102 const VAddr framebuffer_addr = framebuffer->address + framebuffer->offset; 135 const VAddr framebuffer_addr = framebuffer->address + framebuffer->offset;
103 const bool use_accelerated = 136 const bool use_accelerated =
104 rasterizer->AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride); 137 rasterizer.AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride);
105 const bool is_srgb = use_accelerated && screen_info.is_srgb; 138 const bool is_srgb = use_accelerated && screen_info.is_srgb;
106 if (swapchain->HasFramebufferChanged(layout) || swapchain->GetSrgbState() != is_srgb) { 139 if (swapchain.HasFramebufferChanged(layout) || swapchain.GetSrgbState() != is_srgb) {
107 swapchain->Create(layout.width, layout.height, is_srgb); 140 swapchain.Create(layout.width, layout.height, is_srgb);
108 blit_screen->Recreate(); 141 blit_screen.Recreate();
109 } 142 }
110 143
111 scheduler->WaitWorker(); 144 scheduler.WaitWorker();
112 145
113 swapchain->AcquireNextImage(); 146 swapchain.AcquireNextImage();
114 const VkSemaphore render_semaphore = blit_screen->Draw(*framebuffer, use_accelerated); 147 const VkSemaphore render_semaphore = blit_screen.Draw(*framebuffer, use_accelerated);
115 148
116 scheduler->Flush(render_semaphore); 149 scheduler.Flush(render_semaphore);
117 150
118 if (swapchain->Present(render_semaphore)) { 151 if (swapchain.Present(render_semaphore)) {
119 blit_screen->Recreate(); 152 blit_screen.Recreate();
120 } 153 }
121 154 rasterizer.TickFrame();
122 rasterizer->TickFrame();
123 } 155 }
124 156
125 render_window.OnFrameDisplayed(); 157 render_window.OnFrameDisplayed();
126} 158}
127 159
128bool RendererVulkan::Init() try {
129 library = OpenLibrary();
130 instance = CreateInstance(library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type,
131 true, Settings::values.renderer_debug);
132 if (Settings::values.renderer_debug) {
133 debug_callback = CreateDebugCallback(instance);
134 }
135 surface = CreateSurface(instance, render_window);
136
137 InitializeDevice();
138 Report();
139
140 memory_allocator = std::make_unique<MemoryAllocator>(*device);
141
142 state_tracker = std::make_unique<StateTracker>(gpu);
143
144 scheduler = std::make_unique<VKScheduler>(*device, *state_tracker);
145
146 const auto& framebuffer = render_window.GetFramebufferLayout();
147 swapchain = std::make_unique<VKSwapchain>(*surface, *device, *scheduler);
148 swapchain->Create(framebuffer.width, framebuffer.height, false);
149
150 rasterizer = std::make_unique<RasterizerVulkan>(render_window, gpu, gpu.MemoryManager(),
151 cpu_memory, screen_info, *device,
152 *memory_allocator, *state_tracker, *scheduler);
153
154 blit_screen =
155 std::make_unique<VKBlitScreen>(cpu_memory, render_window, *rasterizer, *device,
156 *memory_allocator, *swapchain, *scheduler, screen_info);
157 return true;
158
159} catch (const vk::Exception& exception) {
160 LOG_ERROR(Render_Vulkan, "Vulkan initialization failed with error: {}", exception.what());
161 return false;
162}
163
164void RendererVulkan::ShutDown() {
165 if (!device) {
166 return;
167 }
168 if (const auto& dev = device->GetLogical()) {
169 dev.WaitIdle();
170 }
171 rasterizer.reset();
172 blit_screen.reset();
173 scheduler.reset();
174 swapchain.reset();
175 memory_allocator.reset();
176 device.reset();
177}
178
179void RendererVulkan::InitializeDevice() {
180 const std::vector<VkPhysicalDevice> devices = instance.EnumeratePhysicalDevices();
181 const s32 device_index = Settings::values.vulkan_device.GetValue();
182 if (device_index < 0 || device_index >= static_cast<s32>(devices.size())) {
183 LOG_ERROR(Render_Vulkan, "Invalid device index {}!", device_index);
184 throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
185 }
186 const vk::PhysicalDevice physical_device(devices[static_cast<size_t>(device_index)], dld);
187 device = std::make_unique<Device>(*instance, physical_device, *surface, dld);
188}
189
190void RendererVulkan::Report() const { 160void RendererVulkan::Report() const {
191 const std::string vendor_name{device->GetVendorName()}; 161 const std::string vendor_name{device.GetVendorName()};
192 const std::string model_name{device->GetModelName()}; 162 const std::string model_name{device.GetModelName()};
193 const std::string driver_version = GetDriverVersion(*device); 163 const std::string driver_version = GetDriverVersion(device);
194 const std::string driver_name = fmt::format("{} {}", vendor_name, driver_version); 164 const std::string driver_name = fmt::format("{} {}", vendor_name, driver_version);
195 165
196 const std::string api_version = GetReadableVersion(device->ApiVersion()); 166 const std::string api_version = GetReadableVersion(device.ApiVersion());
197 167
198 const std::string extensions = BuildCommaSeparatedExtensions(device->GetAvailableExtensions()); 168 const std::string extensions = BuildCommaSeparatedExtensions(device.GetAvailableExtensions());
199 169
200 LOG_INFO(Render_Vulkan, "Driver: {}", driver_name); 170 LOG_INFO(Render_Vulkan, "Driver: {}", driver_name);
201 LOG_INFO(Render_Vulkan, "Device: {}", model_name); 171 LOG_INFO(Render_Vulkan, "Device: {}", model_name);
@@ -209,21 +179,4 @@ void RendererVulkan::Report() const {
209 telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions); 179 telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions);
210} 180}
211 181
212std::vector<std::string> RendererVulkan::EnumerateDevices() try {
213 vk::InstanceDispatch dld;
214 const Common::DynamicLibrary library = OpenLibrary();
215 const vk::Instance instance = CreateInstance(library, dld, VK_API_VERSION_1_0);
216 const std::vector<VkPhysicalDevice> physical_devices = instance.EnumeratePhysicalDevices();
217 std::vector<std::string> names;
218 names.reserve(physical_devices.size());
219 for (const VkPhysicalDevice device : physical_devices) {
220 names.push_back(vk::PhysicalDevice(device, dld).GetProperties().deviceName);
221 }
222 return names;
223
224} catch (const vk::Exception& exception) {
225 LOG_ERROR(Render_Vulkan, "Failed to enumerate devices with error: {}", exception.what());
226 return {};
227}
228
229} // namespace Vulkan 182} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h
index daf55b9b4..1efaf3b77 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.h
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.h
@@ -9,8 +9,14 @@
9#include <vector> 9#include <vector>
10 10
11#include "common/dynamic_library.h" 11#include "common/dynamic_library.h"
12
13#include "video_core/renderer_base.h" 12#include "video_core/renderer_base.h"
13#include "video_core/renderer_vulkan/vk_blit_screen.h"
14#include "video_core/renderer_vulkan/vk_rasterizer.h"
15#include "video_core/renderer_vulkan/vk_scheduler.h"
16#include "video_core/renderer_vulkan/vk_state_tracker.h"
17#include "video_core/renderer_vulkan/vk_swapchain.h"
18#include "video_core/vulkan_common/vulkan_device.h"
19#include "video_core/vulkan_common/vulkan_memory_allocator.h"
14#include "video_core/vulkan_common/vulkan_wrapper.h" 20#include "video_core/vulkan_common/vulkan_wrapper.h"
15 21
16namespace Core { 22namespace Core {
@@ -27,20 +33,6 @@ class GPU;
27 33
28namespace Vulkan { 34namespace Vulkan {
29 35
30class Device;
31class StateTracker;
32class MemoryAllocator;
33class VKBlitScreen;
34class VKSwapchain;
35class VKScheduler;
36
37struct VKScreenInfo {
38 VkImageView image_view{};
39 u32 width{};
40 u32 height{};
41 bool is_srgb{};
42};
43
44class RendererVulkan final : public VideoCore::RendererBase { 36class RendererVulkan final : public VideoCore::RendererBase {
45public: 37public:
46 explicit RendererVulkan(Core::TelemetrySession& telemtry_session, 38 explicit RendererVulkan(Core::TelemetrySession& telemtry_session,
@@ -49,15 +41,13 @@ public:
49 std::unique_ptr<Core::Frontend::GraphicsContext> context_); 41 std::unique_ptr<Core::Frontend::GraphicsContext> context_);
50 ~RendererVulkan() override; 42 ~RendererVulkan() override;
51 43
52 bool Init() override;
53 void ShutDown() override;
54 void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override; 44 void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override;
55 45
56 static std::vector<std::string> EnumerateDevices(); 46 VideoCore::RasterizerInterface* ReadRasterizer() override {
47 return &rasterizer;
48 }
57 49
58private: 50private:
59 void InitializeDevice();
60
61 void Report() const; 51 void Report() const;
62 52
63 Core::TelemetrySession& telemetry_session; 53 Core::TelemetrySession& telemetry_session;
@@ -74,12 +64,13 @@ private:
74 VKScreenInfo screen_info; 64 VKScreenInfo screen_info;
75 65
76 vk::DebugUtilsMessenger debug_callback; 66 vk::DebugUtilsMessenger debug_callback;
77 std::unique_ptr<Device> device; 67 Device device;
78 std::unique_ptr<MemoryAllocator> memory_allocator; 68 MemoryAllocator memory_allocator;
79 std::unique_ptr<StateTracker> state_tracker; 69 StateTracker state_tracker;
80 std::unique_ptr<VKScheduler> scheduler; 70 VKScheduler scheduler;
81 std::unique_ptr<VKSwapchain> swapchain; 71 VKSwapchain swapchain;
82 std::unique_ptr<VKBlitScreen> blit_screen; 72 VKBlitScreen blit_screen;
73 RasterizerVulkan rasterizer;
83}; 74};
84 75
85} // namespace Vulkan 76} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
index 3e3b895e0..df8992528 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
@@ -18,7 +18,6 @@
18#include "video_core/gpu.h" 18#include "video_core/gpu.h"
19#include "video_core/host_shaders/vulkan_present_frag_spv.h" 19#include "video_core/host_shaders/vulkan_present_frag_spv.h"
20#include "video_core/host_shaders/vulkan_present_vert_spv.h" 20#include "video_core/host_shaders/vulkan_present_vert_spv.h"
21#include "video_core/rasterizer_interface.h"
22#include "video_core/renderer_vulkan/renderer_vulkan.h" 21#include "video_core/renderer_vulkan/renderer_vulkan.h"
23#include "video_core/renderer_vulkan/vk_blit_screen.h" 22#include "video_core/renderer_vulkan/vk_blit_screen.h"
24#include "video_core/renderer_vulkan/vk_master_semaphore.h" 23#include "video_core/renderer_vulkan/vk_master_semaphore.h"
@@ -113,13 +112,12 @@ struct VKBlitScreen::BufferData {
113}; 112};
114 113
115VKBlitScreen::VKBlitScreen(Core::Memory::Memory& cpu_memory_, 114VKBlitScreen::VKBlitScreen(Core::Memory::Memory& cpu_memory_,
116 Core::Frontend::EmuWindow& render_window_, 115 Core::Frontend::EmuWindow& render_window_, const Device& device_,
117 VideoCore::RasterizerInterface& rasterizer_, const Device& device_,
118 MemoryAllocator& memory_allocator_, VKSwapchain& swapchain_, 116 MemoryAllocator& memory_allocator_, VKSwapchain& swapchain_,
119 VKScheduler& scheduler_, const VKScreenInfo& screen_info_) 117 VKScheduler& scheduler_, const VKScreenInfo& screen_info_)
120 : cpu_memory{cpu_memory_}, render_window{render_window_}, rasterizer{rasterizer_}, 118 : cpu_memory{cpu_memory_}, render_window{render_window_}, device{device_},
121 device{device_}, memory_allocator{memory_allocator_}, swapchain{swapchain_}, 119 memory_allocator{memory_allocator_}, swapchain{swapchain_}, scheduler{scheduler_},
122 scheduler{scheduler_}, image_count{swapchain.GetImageCount()}, screen_info{screen_info_} { 120 image_count{swapchain.GetImageCount()}, screen_info{screen_info_} {
123 resource_ticks.resize(image_count); 121 resource_ticks.resize(image_count);
124 122
125 CreateStaticResources(); 123 CreateStaticResources();
@@ -159,7 +157,6 @@ VkSemaphore VKBlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer, bool
159 const VAddr framebuffer_addr = framebuffer.address + framebuffer.offset; 157 const VAddr framebuffer_addr = framebuffer.address + framebuffer.offset;
160 const u8* const host_ptr = cpu_memory.GetPointer(framebuffer_addr); 158 const u8* const host_ptr = cpu_memory.GetPointer(framebuffer_addr);
161 const size_t size_bytes = GetSizeInBytes(framebuffer); 159 const size_t size_bytes = GetSizeInBytes(framebuffer);
162 rasterizer.FlushRegion(ToCacheAddr(host_ptr), size_bytes);
163 160
164 // TODO(Rodrigo): Read this from HLE 161 // TODO(Rodrigo): Read this from HLE
165 constexpr u32 block_height_log2 = 4; 162 constexpr u32 block_height_log2 = 4;
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.h b/src/video_core/renderer_vulkan/vk_blit_screen.h
index b52576957..5e3177685 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.h
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.h
@@ -38,12 +38,18 @@ class RasterizerVulkan;
38class VKScheduler; 38class VKScheduler;
39class VKSwapchain; 39class VKSwapchain;
40 40
41class VKBlitScreen final { 41struct VKScreenInfo {
42 VkImageView image_view{};
43 u32 width{};
44 u32 height{};
45 bool is_srgb{};
46};
47
48class VKBlitScreen {
42public: 49public:
43 explicit VKBlitScreen(Core::Memory::Memory& cpu_memory, 50 explicit VKBlitScreen(Core::Memory::Memory& cpu_memory,
44 Core::Frontend::EmuWindow& render_window, 51 Core::Frontend::EmuWindow& render_window, const Device& device,
45 VideoCore::RasterizerInterface& rasterizer, const Device& device, 52 MemoryAllocator& memory_manager, VKSwapchain& swapchain,
46 MemoryAllocator& memory_allocator, VKSwapchain& swapchain,
47 VKScheduler& scheduler, const VKScreenInfo& screen_info); 53 VKScheduler& scheduler, const VKScreenInfo& screen_info);
48 ~VKBlitScreen(); 54 ~VKBlitScreen();
49 55
@@ -84,7 +90,6 @@ private:
84 90
85 Core::Memory::Memory& cpu_memory; 91 Core::Memory::Memory& cpu_memory;
86 Core::Frontend::EmuWindow& render_window; 92 Core::Frontend::EmuWindow& render_window;
87 VideoCore::RasterizerInterface& rasterizer;
88 const Device& device; 93 const Device& device;
89 MemoryAllocator& memory_allocator; 94 MemoryAllocator& memory_allocator;
90 VKSwapchain& swapchain; 95 VKSwapchain& swapchain;
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp
index 725a2a05d..0b63bd6c8 100644
--- a/src/video_core/renderer_vulkan/vk_swapchain.cpp
+++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp
@@ -56,8 +56,11 @@ VkExtent2D ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities, u32 wi
56 56
57} // Anonymous namespace 57} // Anonymous namespace
58 58
59VKSwapchain::VKSwapchain(VkSurfaceKHR surface_, const Device& device_, VKScheduler& scheduler_) 59VKSwapchain::VKSwapchain(VkSurfaceKHR surface_, const Device& device_, VKScheduler& scheduler_,
60 : surface{surface_}, device{device_}, scheduler{scheduler_} {} 60 u32 width, u32 height, bool srgb)
61 : surface{surface_}, device{device_}, scheduler{scheduler_} {
62 Create(width, height, srgb);
63}
61 64
62VKSwapchain::~VKSwapchain() = default; 65VKSwapchain::~VKSwapchain() = default;
63 66
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.h b/src/video_core/renderer_vulkan/vk_swapchain.h
index 2eadd62b3..a728511e0 100644
--- a/src/video_core/renderer_vulkan/vk_swapchain.h
+++ b/src/video_core/renderer_vulkan/vk_swapchain.h
@@ -20,7 +20,8 @@ class VKScheduler;
20 20
21class VKSwapchain { 21class VKSwapchain {
22public: 22public:
23 explicit VKSwapchain(VkSurfaceKHR surface, const Device& device, VKScheduler& scheduler); 23 explicit VKSwapchain(VkSurfaceKHR surface, const Device& device, VKScheduler& scheduler,
24 u32 width, u32 height, bool srgb);
24 ~VKSwapchain(); 25 ~VKSwapchain();
25 26
26 /// Creates (or recreates) the swapchain with a given size. 27 /// Creates (or recreates) the swapchain with a given size.
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp
index 53444e945..e1b38c6ac 100644
--- a/src/video_core/video_core.cpp
+++ b/src/video_core/video_core.cpp
@@ -38,19 +38,18 @@ namespace VideoCore {
38 38
39std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system) { 39std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system) {
40 const bool use_nvdec = Settings::values.use_nvdec_emulation.GetValue(); 40 const bool use_nvdec = Settings::values.use_nvdec_emulation.GetValue();
41 std::unique_ptr<Tegra::GPU> gpu = std::make_unique<Tegra::GPU>( 41 const bool use_async = Settings::values.use_asynchronous_gpu_emulation.GetValue();
42 system, Settings::values.use_asynchronous_gpu_emulation.GetValue(), use_nvdec); 42 auto gpu = std::make_unique<Tegra::GPU>(system, use_async, use_nvdec);
43
44 auto context = emu_window.CreateSharedContext(); 43 auto context = emu_window.CreateSharedContext();
45 const auto scope = context->Acquire(); 44 auto scope = context->Acquire();
46 45 try {
47 auto renderer = CreateRenderer(system, emu_window, *gpu, std::move(context)); 46 auto renderer = CreateRenderer(system, emu_window, *gpu, std::move(context));
48 if (!renderer->Init()) { 47 gpu->BindRenderer(std::move(renderer));
48 return gpu;
49 } catch (const std::runtime_error& exception) {
50 LOG_ERROR(HW_GPU, "Failed to initialize GPU: {}", exception.what());
49 return nullptr; 51 return nullptr;
50 } 52 }
51
52 gpu->BindRenderer(std::move(renderer));
53 return gpu;
54} 53}
55 54
56u16 GetResolutionScaleFactor(const RendererBase& renderer) { 55u16 GetResolutionScaleFactor(const RendererBase& renderer) {
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h
index 4b66dba7a..f1697b79a 100644
--- a/src/video_core/vulkan_common/vulkan_device.h
+++ b/src/video_core/vulkan_common/vulkan_device.h
@@ -23,7 +23,7 @@ enum class FormatType { Linear, Optimal, Buffer };
23const u32 GuestWarpSize = 32; 23const u32 GuestWarpSize = 32;
24 24
25/// Handles data specific to a physical device. 25/// Handles data specific to a physical device.
26class Device final { 26class Device {
27public: 27public:
28 explicit Device(VkInstance instance, vk::PhysicalDevice physical, VkSurfaceKHR surface, 28 explicit Device(VkInstance instance, vk::PhysicalDevice physical, VkSurfaceKHR surface,
29 const vk::InstanceDispatch& dld); 29 const vk::InstanceDispatch& dld);
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h
index 9689de0cb..4d8f14357 100644
--- a/src/video_core/vulkan_common/vulkan_wrapper.h
+++ b/src/video_core/vulkan_common/vulkan_wrapper.h
@@ -344,6 +344,9 @@ public:
344 /// Construct an empty handle. 344 /// Construct an empty handle.
345 Handle() = default; 345 Handle() = default;
346 346
347 /// Construct an empty handle.
348 Handle(std::nullptr_t) {}
349
347 /// Copying Vulkan objects is not supported and will never be. 350 /// Copying Vulkan objects is not supported and will never be.
348 Handle(const Handle&) = delete; 351 Handle(const Handle&) = delete;
349 Handle& operator=(const Handle&) = delete; 352 Handle& operator=(const Handle&) = delete;
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index d9a3035cb..1c61d419d 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -64,7 +64,7 @@ void EmuThread::run() {
64 64
65 emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0); 65 emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
66 66
67 system.Renderer().Rasterizer().LoadDiskResources( 67 system.Renderer().ReadRasterizer()->LoadDiskResources(
68 system.CurrentProcess()->GetTitleID(), stop_run, 68 system.CurrentProcess()->GetTitleID(), stop_run,
69 [this](VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total) { 69 [this](VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total) {
70 emit LoadProgress(stage, value, total); 70 emit LoadProgress(stage, value, total);
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp
index b78a5dff0..b36d6a7c8 100644
--- a/src/yuzu/configuration/configure_graphics.cpp
+++ b/src/yuzu/configuration/configure_graphics.cpp
@@ -11,7 +11,8 @@
11#include "core/core.h" 11#include "core/core.h"
12#include "core/settings.h" 12#include "core/settings.h"
13#include "ui_configure_graphics.h" 13#include "ui_configure_graphics.h"
14#include "video_core/renderer_vulkan/renderer_vulkan.h" 14#include "video_core/vulkan_common/vulkan_instance.h"
15#include "video_core/vulkan_common/vulkan_library.h"
15#include "yuzu/configuration/configuration_shared.h" 16#include "yuzu/configuration/configuration_shared.h"
16#include "yuzu/configuration/configure_graphics.h" 17#include "yuzu/configuration/configure_graphics.h"
17 18
@@ -212,11 +213,23 @@ void ConfigureGraphics::UpdateDeviceComboBox() {
212 ui->device->setEnabled(enabled && !Core::System::GetInstance().IsPoweredOn()); 213 ui->device->setEnabled(enabled && !Core::System::GetInstance().IsPoweredOn());
213} 214}
214 215
215void ConfigureGraphics::RetrieveVulkanDevices() { 216void ConfigureGraphics::RetrieveVulkanDevices() try {
217 using namespace Vulkan;
218
219 vk::InstanceDispatch dld;
220 const Common::DynamicLibrary library = OpenLibrary();
221 const vk::Instance instance = CreateInstance(library, dld, VK_API_VERSION_1_0);
222 const std::vector<VkPhysicalDevice> physical_devices = instance.EnumeratePhysicalDevices();
223
216 vulkan_devices.clear(); 224 vulkan_devices.clear();
217 for (const auto& name : Vulkan::RendererVulkan::EnumerateDevices()) { 225 vulkan_devices.reserve(physical_devices.size());
226 for (const VkPhysicalDevice device : physical_devices) {
227 const char* const name = vk::PhysicalDevice(device, dld).GetProperties().deviceName;
218 vulkan_devices.push_back(QString::fromStdString(name)); 228 vulkan_devices.push_back(QString::fromStdString(name));
219 } 229 }
230
231} catch (const Vulkan::vk::Exception& exception) {
232 LOG_ERROR(Frontend, "Failed to enumerate devices with error: {}", exception.what());
220} 233}
221 234
222Settings::RendererBackend ConfigureGraphics::GetCurrentGraphicsBackend() const { 235Settings::RendererBackend ConfigureGraphics::GetCurrentGraphicsBackend() const {
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp
index 0e1f3bdb3..982c41785 100644
--- a/src/yuzu_cmd/yuzu.cpp
+++ b/src/yuzu_cmd/yuzu.cpp
@@ -215,7 +215,7 @@ int main(int argc, char** argv) {
215 // Core is loaded, start the GPU (makes the GPU contexts current to this thread) 215 // Core is loaded, start the GPU (makes the GPU contexts current to this thread)
216 system.GPU().Start(); 216 system.GPU().Start();
217 217
218 system.Renderer().Rasterizer().LoadDiskResources( 218 system.Renderer().ReadRasterizer()->LoadDiskResources(
219 system.CurrentProcess()->GetTitleID(), false, 219 system.CurrentProcess()->GetTitleID(), false,
220 [](VideoCore::LoadCallbackStage, size_t value, size_t total) {}); 220 [](VideoCore::LoadCallbackStage, size_t value, size_t total) {});
221 221