aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorReinUsesLisp <[email protected]>2021-01-05 04:09:39 -0300
committerReinUsesLisp <[email protected]>2021-02-13 02:16:19 -0300
commit75ccd9959ca7aa78b71fbb800ed2127d8613e9dc (patch)
tree3b9b5c0779cff69ef135bb3394ae70a0d3a9804d /src
parent19156292a374ddf15c6e8679f93d146a6d305fd6 (diff)
downloadyuzu-android-75ccd9959ca7aa78b71fbb800ed2127d8613e9dc.tar.gz
yuzu-android-75ccd9959ca7aa78b71fbb800ed2127d8613e9dc.zip
gpu: Report renderer errors with exceptions
Instead of using a two step initialization to report errors, initialize the GPU renderer and rasterizer on the constructor and report errors through std::runtime_error.
Diffstat (limited to 'src')
-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() {
Fermi2D::~Fermi2D() = default;
-void Fermi2D::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
- rasterizer = &rasterizer_;
+void Fermi2D::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) {
+ rasterizer = rasterizer_;
}
void 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:
~Fermi2D();
/// Binds a rasterizer to this engine.
- void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
+ void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
/// Write the value to the register identified by method.
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
KeplerCompute::~KeplerCompute() = default;
-void KeplerCompute::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
- rasterizer = &rasterizer_;
+void KeplerCompute::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) {
+ rasterizer = rasterizer_;
}
void 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:
~KeplerCompute();
/// Binds a rasterizer to this engine.
- void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
+ void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
static constexpr std::size_t NumConstBuffers = 8;
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_)
Maxwell3D::~Maxwell3D() = default;
-void Maxwell3D::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
- rasterizer = &rasterizer_;
+void Maxwell3D::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) {
+ rasterizer = rasterizer_;
}
void 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:
~Maxwell3D();
/// Binds a rasterizer to this engine.
- void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
+ void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
/// Register structure of the Maxwell3D engine.
/// 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;
void GPU::BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer_) {
renderer = std::move(renderer_);
+ rasterizer = renderer->ReadRasterizer();
- VideoCore::RasterizerInterface& rasterizer = renderer->Rasterizer();
memory_manager->BindRasterizer(rasterizer);
maxwell_3d->BindRasterizer(rasterizer);
fermi_2d->BindRasterizer(rasterizer);
@@ -171,7 +171,7 @@ void GPU::TickWork() {
const std::size_t size = request.size;
flush_requests.pop_front();
flush_request_mutex.unlock();
- renderer->Rasterizer().FlushRegion(addr, size);
+ rasterizer->FlushRegion(addr, size);
current_flush_fence.store(fence);
flush_request_mutex.lock();
}
@@ -193,11 +193,11 @@ u64 GPU::GetTicks() const {
}
void GPU::FlushCommands() {
- renderer->Rasterizer().FlushCommands();
+ rasterizer->FlushCommands();
}
void GPU::SyncGuestHost() {
- renderer->Rasterizer().SyncGuestHost();
+ rasterizer->SyncGuestHost();
}
enum 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:
std::unique_ptr<Tegra::DmaPusher> dma_pusher;
std::unique_ptr<Tegra::CDmaPusher> cdma_pusher;
std::unique_ptr<VideoCore::RendererBase> renderer;
+ VideoCore::RasterizerInterface* rasterizer = nullptr;
const bool use_nvdec;
private:
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,
}
auto current_context = context.Acquire();
+ VideoCore::RasterizerInterface* const rasterizer = renderer.ReadRasterizer();
CommandDataContainer next;
while (state.is_running) {
@@ -52,13 +53,13 @@ static void RunThread(Core::System& system, VideoCore::RendererBase& renderer,
} else if (const auto* data = std::get_if<SwapBuffersCommand>(&next.data)) {
renderer.SwapBuffers(data->framebuffer ? &*data->framebuffer : nullptr);
} else if (std::holds_alternative<OnCommandListEndCommand>(next.data)) {
- renderer.Rasterizer().ReleaseFences();
+ rasterizer->ReleaseFences();
} else if (std::holds_alternative<GPUTickCommand>(next.data)) {
system.GPU().TickWork();
} else if (const auto* flush = std::get_if<FlushRegionCommand>(&next.data)) {
- renderer.Rasterizer().FlushRegion(flush->addr, flush->size);
+ rasterizer->FlushRegion(flush->addr, flush->size);
} else if (const auto* invalidate = std::get_if<InvalidateRegionCommand>(&next.data)) {
- renderer.Rasterizer().OnCPUWrite(invalidate->addr, invalidate->size);
+ rasterizer->OnCPUWrite(invalidate->addr, invalidate->size);
} else if (std::holds_alternative<EndProcessingCommand>(next.data)) {
return;
} else {
@@ -84,6 +85,7 @@ ThreadManager::~ThreadManager() {
void ThreadManager::StartThread(VideoCore::RendererBase& renderer,
Core::Frontend::GraphicsContext& context,
Tegra::DmaPusher& dma_pusher, Tegra::CDmaPusher& cdma_pusher) {
+ rasterizer = renderer.ReadRasterizer();
thread = std::thread(RunThread, std::ref(system), std::ref(renderer), std::ref(context),
std::ref(dma_pusher), std::ref(state), std::ref(cdma_pusher));
}
@@ -129,12 +131,12 @@ void ThreadManager::FlushRegion(VAddr addr, u64 size) {
}
void ThreadManager::InvalidateRegion(VAddr addr, u64 size) {
- system.Renderer().Rasterizer().OnCPUWrite(addr, size);
+ rasterizer->OnCPUWrite(addr, size);
}
void ThreadManager::FlushAndInvalidateRegion(VAddr addr, u64 size) {
// Skip flush on asynch mode, as FlushAndInvalidateRegion is not used for anything too important
- system.Renderer().Rasterizer().OnCPUWrite(addr, size);
+ rasterizer->OnCPUWrite(addr, size);
}
void 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;
} // namespace Core
namespace VideoCore {
+class RasterizerInterface;
class RendererBase;
} // namespace VideoCore
@@ -151,11 +152,12 @@ private:
/// Pushes a command to be executed by the GPU thread
u64 PushCommand(CommandData&& command_data);
- SynchState state;
Core::System& system;
- std::thread thread;
- std::thread::id thread_id;
const bool is_async;
+ VideoCore::RasterizerInterface* rasterizer = nullptr;
+
+ SynchState state;
+ std::thread thread;
};
} // 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_)
MemoryManager::~MemoryManager() = default;
-void MemoryManager::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
- rasterizer = &rasterizer_;
+void MemoryManager::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) {
+ rasterizer = rasterizer_;
}
GPUVAddr 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:
~MemoryManager();
/// Binds a renderer to the memory manager.
- void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
+ void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
[[nodiscard]] std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr) const;
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:
std::unique_ptr<Core::Frontend::GraphicsContext> context);
virtual ~RendererBase();
- /// Initialize the renderer
- [[nodiscard]] virtual bool Init() = 0;
-
- /// Shutdown the renderer
- virtual void ShutDown() = 0;
-
/// Finalize rendering the guest frame and draw into the presentation texture
virtual void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) = 0;
+ [[nodiscard]] virtual RasterizerInterface* ReadRasterizer() = 0;
+
// Getter/setter functions:
// ------------------------
@@ -57,14 +53,6 @@ public:
return m_current_frame;
}
- [[nodiscard]] RasterizerInterface& Rasterizer() {
- return *rasterizer;
- }
-
- [[nodiscard]] const RasterizerInterface& Rasterizer() const {
- return *rasterizer;
- }
-
[[nodiscard]] Core::Frontend::GraphicsContext& Context() {
return *context;
}
@@ -98,7 +86,6 @@ public:
protected:
Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle.
- std::unique_ptr<RasterizerInterface> rasterizer;
std::unique_ptr<Core::Frontend::GraphicsContext> context;
f32 m_current_fps = 0.0f; ///< Current framerate, should be set by the renderer
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_,
Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_,
std::unique_ptr<Core::Frontend::GraphicsContext> context_)
: RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_},
- emu_window{emu_window_}, cpu_memory{cpu_memory_}, gpu{gpu_}, program_manager{device} {}
+ emu_window{emu_window_}, cpu_memory{cpu_memory_}, gpu{gpu_}, program_manager{device},
+ rasterizer{emu_window, gpu, cpu_memory, device, screen_info, program_manager, state_tracker} {
+ if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) {
+ glEnable(GL_DEBUG_OUTPUT);
+ glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+ glDebugMessageCallback(DebugHandler, nullptr);
+ }
+ AddTelemetryFields();
+
+ if (!GLAD_GL_VERSION_4_6) {
+ throw std::runtime_error{"OpenGL 4.3 is not available"};
+ }
+ InitOpenGLObjects();
+}
RendererOpenGL::~RendererOpenGL() = default;
@@ -148,7 +161,7 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
++m_current_frame;
- rasterizer->TickFrame();
+ rasterizer.TickFrame();
context->SwapBuffers();
render_window.OnFrameDisplayed();
@@ -179,7 +192,7 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf
framebuffer_crop_rect = framebuffer.crop_rect;
const VAddr framebuffer_addr{framebuffer.address + framebuffer.offset};
- if (rasterizer->AccelerateDisplay(framebuffer, framebuffer_addr, framebuffer.stride)) {
+ if (rasterizer.AccelerateDisplay(framebuffer, framebuffer_addr, framebuffer.stride)) {
return;
}
@@ -289,14 +302,6 @@ void RendererOpenGL::AddTelemetryFields() {
telemetry_session.AddField(user_system, "GPU_OpenGL_Version", std::string(gl_version));
}
-void RendererOpenGL::CreateRasterizer() {
- if (rasterizer) {
- return;
- }
- rasterizer = std::make_unique<RasterizerOpenGL>(emu_window, gpu, cpu_memory, device,
- screen_info, program_manager, state_tracker);
-}
-
void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
const Tegra::FramebufferConfig& framebuffer) {
texture.width = framebuffer.width;
@@ -497,25 +502,4 @@ void RendererOpenGL::RenderScreenshot() {
renderer_settings.screenshot_requested = false;
}
-bool RendererOpenGL::Init() {
- if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) {
- glEnable(GL_DEBUG_OUTPUT);
- glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
- glDebugMessageCallback(DebugHandler, nullptr);
- }
-
- AddTelemetryFields();
-
- if (!GLAD_GL_VERSION_4_6) {
- return false;
- }
-
- InitOpenGLObjects();
- CreateRasterizer();
-
- return true;
-}
-
-void RendererOpenGL::ShutDown() {}
-
} // 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 @@
#include "common/math_util.h"
#include "video_core/renderer_base.h"
#include "video_core/renderer_opengl/gl_device.h"
+#include "video_core/renderer_opengl/gl_rasterizer.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"
#include "video_core/renderer_opengl/gl_shader_manager.h"
#include "video_core/renderer_opengl/gl_state_tracker.h"
@@ -63,18 +64,18 @@ public:
std::unique_ptr<Core::Frontend::GraphicsContext> context_);
~RendererOpenGL() override;
- bool Init() override;
- void ShutDown() override;
void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override;
+ VideoCore::RasterizerInterface* ReadRasterizer() override {
+ return &rasterizer;
+ }
+
private:
/// Initializes the OpenGL state and creates persistent objects.
void InitOpenGLObjects();
void AddTelemetryFields();
- void CreateRasterizer();
-
void ConfigureFramebufferTexture(TextureInfo& texture,
const Tegra::FramebufferConfig& framebuffer);
@@ -118,6 +119,8 @@ private:
/// Global dummy shader pipeline
ProgramManager program_manager;
+ RasterizerOpenGL rasterizer;
+
/// OpenGL framebuffer data
std::vector<u8> gl_framebuffer_data;
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
return separated_extensions;
}
+Device CreateDevice(const vk::Instance& instance, const vk::InstanceDispatch& dld,
+ VkSurfaceKHR surface) {
+ const std::vector<VkPhysicalDevice> devices = instance.EnumeratePhysicalDevices();
+ const s32 device_index = Settings::values.vulkan_device.GetValue();
+ if (device_index < 0 || device_index >= static_cast<s32>(devices.size())) {
+ LOG_ERROR(Render_Vulkan, "Invalid device index {}!", device_index);
+ throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
+ }
+ const vk::PhysicalDevice physical_device(devices[device_index], dld);
+ return Device(*instance, physical_device, surface, dld);
+}
} // Anonymous namespace
RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_,
Core::Frontend::EmuWindow& emu_window,
Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_,
- std::unique_ptr<Core::Frontend::GraphicsContext> context_)
- : RendererBase{emu_window, std::move(context_)}, telemetry_session{telemetry_session_},
- cpu_memory{cpu_memory_}, gpu{gpu_} {}
+ std::unique_ptr<Core::Frontend::GraphicsContext> context_) try
+ : RendererBase(emu_window, std::move(context_)),
+ telemetry_session(telemetry_session_),
+ cpu_memory(cpu_memory_),
+ gpu(gpu_),
+ library(OpenLibrary()),
+ instance(CreateInstance(library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type,
+ true, Settings::values.renderer_debug)),
+ debug_callback(Settings::values.renderer_debug ? CreateDebugCallback(instance) : nullptr),
+ surface(CreateSurface(instance, render_window)),
+ device(CreateDevice(instance, dld, *surface)),
+ memory_allocator(device),
+ state_tracker(gpu),
+ scheduler(device, state_tracker),
+ swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width,
+ render_window.GetFramebufferLayout().height, false),
+ blit_screen(cpu_memory, render_window, device, memory_allocator, swapchain, scheduler,
+ screen_info),
+ rasterizer(render_window, gpu, gpu.MemoryManager(), cpu_memory, screen_info, device,
+ memory_allocator, state_tracker, scheduler) {
+ Report();
+} catch (const vk::Exception& exception) {
+ LOG_ERROR(Render_Vulkan, "Vulkan initialization failed with error: {}", exception.what());
+ throw std::runtime_error{fmt::format("Vulkan initialization error {}", exception.what())};
+}
RendererVulkan::~RendererVulkan() {
- ShutDown();
+ void(device.GetLogical().WaitIdle());
}
void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
@@ -101,101 +134,38 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
if (layout.width > 0 && layout.height > 0 && render_window.IsShown()) {
const VAddr framebuffer_addr = framebuffer->address + framebuffer->offset;
const bool use_accelerated =
- rasterizer->AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride);
+ rasterizer.AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride);
const bool is_srgb = use_accelerated && screen_info.is_srgb;
- if (swapchain->HasFramebufferChanged(layout) || swapchain->GetSrgbState() != is_srgb) {
- swapchain->Create(layout.width, layout.height, is_srgb);
- blit_screen->Recreate();
+ if (swapchain.HasFramebufferChanged(layout) || swapchain.GetSrgbState() != is_srgb) {
+ swapchain.Create(layout.width, layout.height, is_srgb);
+ blit_screen.Recreate();
}
- scheduler->WaitWorker();
+ scheduler.WaitWorker();
- swapchain->AcquireNextImage();
- const VkSemaphore render_semaphore = blit_screen->Draw(*framebuffer, use_accelerated);
+ swapchain.AcquireNextImage();
+ const VkSemaphore render_semaphore = blit_screen.Draw(*framebuffer, use_accelerated);
- scheduler->Flush(render_semaphore);
+ scheduler.Flush(render_semaphore);
- if (swapchain->Present(render_semaphore)) {
- blit_screen->Recreate();
+ if (swapchain.Present(render_semaphore)) {
+ blit_screen.Recreate();
}
-
- rasterizer->TickFrame();
+ rasterizer.TickFrame();
}
render_window.OnFrameDisplayed();
}
-bool RendererVulkan::Init() try {
- library = OpenLibrary();
- instance = CreateInstance(library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type,
- true, Settings::values.renderer_debug);
- if (Settings::values.renderer_debug) {
- debug_callback = CreateDebugCallback(instance);
- }
- surface = CreateSurface(instance, render_window);
-
- InitializeDevice();
- Report();
-
- memory_allocator = std::make_unique<MemoryAllocator>(*device);
-
- state_tracker = std::make_unique<StateTracker>(gpu);
-
- scheduler = std::make_unique<VKScheduler>(*device, *state_tracker);
-
- const auto& framebuffer = render_window.GetFramebufferLayout();
- swapchain = std::make_unique<VKSwapchain>(*surface, *device, *scheduler);
- swapchain->Create(framebuffer.width, framebuffer.height, false);
-
- rasterizer = std::make_unique<RasterizerVulkan>(render_window, gpu, gpu.MemoryManager(),
- cpu_memory, screen_info, *device,
- *memory_allocator, *state_tracker, *scheduler);
-
- blit_screen =
- std::make_unique<VKBlitScreen>(cpu_memory, render_window, *rasterizer, *device,
- *memory_allocator, *swapchain, *scheduler, screen_info);
- return true;
-
-} catch (const vk::Exception& exception) {
- LOG_ERROR(Render_Vulkan, "Vulkan initialization failed with error: {}", exception.what());
- return false;
-}
-
-void RendererVulkan::ShutDown() {
- if (!device) {
- return;
- }
- if (const auto& dev = device->GetLogical()) {
- dev.WaitIdle();
- }
- rasterizer.reset();
- blit_screen.reset();
- scheduler.reset();
- swapchain.reset();
- memory_allocator.reset();
- device.reset();
-}
-
-void RendererVulkan::InitializeDevice() {
- const std::vector<VkPhysicalDevice> devices = instance.EnumeratePhysicalDevices();
- const s32 device_index = Settings::values.vulkan_device.GetValue();
- if (device_index < 0 || device_index >= static_cast<s32>(devices.size())) {
- LOG_ERROR(Render_Vulkan, "Invalid device index {}!", device_index);
- throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
- }
- const vk::PhysicalDevice physical_device(devices[static_cast<size_t>(device_index)], dld);
- device = std::make_unique<Device>(*instance, physical_device, *surface, dld);
-}
-
void RendererVulkan::Report() const {
- const std::string vendor_name{device->GetVendorName()};
- const std::string model_name{device->GetModelName()};
- const std::string driver_version = GetDriverVersion(*device);
+ const std::string vendor_name{device.GetVendorName()};
+ const std::string model_name{device.GetModelName()};
+ const std::string driver_version = GetDriverVersion(device);
const std::string driver_name = fmt::format("{} {}", vendor_name, driver_version);
- const std::string api_version = GetReadableVersion(device->ApiVersion());
+ const std::string api_version = GetReadableVersion(device.ApiVersion());
- const std::string extensions = BuildCommaSeparatedExtensions(device->GetAvailableExtensions());
+ const std::string extensions = BuildCommaSeparatedExtensions(device.GetAvailableExtensions());
LOG_INFO(Render_Vulkan, "Driver: {}", driver_name);
LOG_INFO(Render_Vulkan, "Device: {}", model_name);
@@ -209,21 +179,4 @@ void RendererVulkan::Report() const {
telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions);
}
-std::vector<std::string> RendererVulkan::EnumerateDevices() try {
- vk::InstanceDispatch dld;
- const Common::DynamicLibrary library = OpenLibrary();
- const vk::Instance instance = CreateInstance(library, dld, VK_API_VERSION_1_0);
- const std::vector<VkPhysicalDevice> physical_devices = instance.EnumeratePhysicalDevices();
- std::vector<std::string> names;
- names.reserve(physical_devices.size());
- for (const VkPhysicalDevice device : physical_devices) {
- names.push_back(vk::PhysicalDevice(device, dld).GetProperties().deviceName);
- }
- return names;
-
-} catch (const vk::Exception& exception) {
- LOG_ERROR(Render_Vulkan, "Failed to enumerate devices with error: {}", exception.what());
- return {};
-}
-
} // 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 @@
#include <vector>
#include "common/dynamic_library.h"
-
#include "video_core/renderer_base.h"
+#include "video_core/renderer_vulkan/vk_blit_screen.h"
+#include "video_core/renderer_vulkan/vk_rasterizer.h"
+#include "video_core/renderer_vulkan/vk_scheduler.h"
+#include "video_core/renderer_vulkan/vk_state_tracker.h"
+#include "video_core/renderer_vulkan/vk_swapchain.h"
+#include "video_core/vulkan_common/vulkan_device.h"
+#include "video_core/vulkan_common/vulkan_memory_allocator.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
namespace Core {
@@ -27,20 +33,6 @@ class GPU;
namespace Vulkan {
-class Device;
-class StateTracker;
-class MemoryAllocator;
-class VKBlitScreen;
-class VKSwapchain;
-class VKScheduler;
-
-struct VKScreenInfo {
- VkImageView image_view{};
- u32 width{};
- u32 height{};
- bool is_srgb{};
-};
-
class RendererVulkan final : public VideoCore::RendererBase {
public:
explicit RendererVulkan(Core::TelemetrySession& telemtry_session,
@@ -49,15 +41,13 @@ public:
std::unique_ptr<Core::Frontend::GraphicsContext> context_);
~RendererVulkan() override;
- bool Init() override;
- void ShutDown() override;
void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override;
- static std::vector<std::string> EnumerateDevices();
+ VideoCore::RasterizerInterface* ReadRasterizer() override {
+ return &rasterizer;
+ }
private:
- void InitializeDevice();
-
void Report() const;
Core::TelemetrySession& telemetry_session;
@@ -74,12 +64,13 @@ private:
VKScreenInfo screen_info;
vk::DebugUtilsMessenger debug_callback;
- std::unique_ptr<Device> device;
- std::unique_ptr<MemoryAllocator> memory_allocator;
- std::unique_ptr<StateTracker> state_tracker;
- std::unique_ptr<VKScheduler> scheduler;
- std::unique_ptr<VKSwapchain> swapchain;
- std::unique_ptr<VKBlitScreen> blit_screen;
+ Device device;
+ MemoryAllocator memory_allocator;
+ StateTracker state_tracker;
+ VKScheduler scheduler;
+ VKSwapchain swapchain;
+ VKBlitScreen blit_screen;
+ RasterizerVulkan rasterizer;
};
} // 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 @@
#include "video_core/gpu.h"
#include "video_core/host_shaders/vulkan_present_frag_spv.h"
#include "video_core/host_shaders/vulkan_present_vert_spv.h"
-#include "video_core/rasterizer_interface.h"
#include "video_core/renderer_vulkan/renderer_vulkan.h"
#include "video_core/renderer_vulkan/vk_blit_screen.h"
#include "video_core/renderer_vulkan/vk_master_semaphore.h"
@@ -113,13 +112,12 @@ struct VKBlitScreen::BufferData {
};
VKBlitScreen::VKBlitScreen(Core::Memory::Memory& cpu_memory_,
- Core::Frontend::EmuWindow& render_window_,
- VideoCore::RasterizerInterface& rasterizer_, const Device& device_,
+ Core::Frontend::EmuWindow& render_window_, const Device& device_,
MemoryAllocator& memory_allocator_, VKSwapchain& swapchain_,
VKScheduler& scheduler_, const VKScreenInfo& screen_info_)
- : cpu_memory{cpu_memory_}, render_window{render_window_}, rasterizer{rasterizer_},
- device{device_}, memory_allocator{memory_allocator_}, swapchain{swapchain_},
- scheduler{scheduler_}, image_count{swapchain.GetImageCount()}, screen_info{screen_info_} {
+ : cpu_memory{cpu_memory_}, render_window{render_window_}, device{device_},
+ memory_allocator{memory_allocator_}, swapchain{swapchain_}, scheduler{scheduler_},
+ image_count{swapchain.GetImageCount()}, screen_info{screen_info_} {
resource_ticks.resize(image_count);
CreateStaticResources();
@@ -159,7 +157,6 @@ VkSemaphore VKBlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer, bool
const VAddr framebuffer_addr = framebuffer.address + framebuffer.offset;
const u8* const host_ptr = cpu_memory.GetPointer(framebuffer_addr);
const size_t size_bytes = GetSizeInBytes(framebuffer);
- rasterizer.FlushRegion(ToCacheAddr(host_ptr), size_bytes);
// TODO(Rodrigo): Read this from HLE
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;
class VKScheduler;
class VKSwapchain;
-class VKBlitScreen final {
+struct VKScreenInfo {
+ VkImageView image_view{};
+ u32 width{};
+ u32 height{};
+ bool is_srgb{};
+};
+
+class VKBlitScreen {
public:
explicit VKBlitScreen(Core::Memory::Memory& cpu_memory,
- Core::Frontend::EmuWindow& render_window,
- VideoCore::RasterizerInterface& rasterizer, const Device& device,
- MemoryAllocator& memory_allocator, VKSwapchain& swapchain,
+ Core::Frontend::EmuWindow& render_window, const Device& device,
+ MemoryAllocator& memory_manager, VKSwapchain& swapchain,
VKScheduler& scheduler, const VKScreenInfo& screen_info);
~VKBlitScreen();
@@ -84,7 +90,6 @@ private:
Core::Memory::Memory& cpu_memory;
Core::Frontend::EmuWindow& render_window;
- VideoCore::RasterizerInterface& rasterizer;
const Device& device;
MemoryAllocator& memory_allocator;
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
} // Anonymous namespace
-VKSwapchain::VKSwapchain(VkSurfaceKHR surface_, const Device& device_, VKScheduler& scheduler_)
- : surface{surface_}, device{device_}, scheduler{scheduler_} {}
+VKSwapchain::VKSwapchain(VkSurfaceKHR surface_, const Device& device_, VKScheduler& scheduler_,
+ u32 width, u32 height, bool srgb)
+ : surface{surface_}, device{device_}, scheduler{scheduler_} {
+ Create(width, height, srgb);
+}
VKSwapchain::~VKSwapchain() = default;
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;
class VKSwapchain {
public:
- explicit VKSwapchain(VkSurfaceKHR surface, const Device& device, VKScheduler& scheduler);
+ explicit VKSwapchain(VkSurfaceKHR surface, const Device& device, VKScheduler& scheduler,
+ u32 width, u32 height, bool srgb);
~VKSwapchain();
/// 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 {
std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system) {
const bool use_nvdec = Settings::values.use_nvdec_emulation.GetValue();
- std::unique_ptr<Tegra::GPU> gpu = std::make_unique<Tegra::GPU>(
- system, Settings::values.use_asynchronous_gpu_emulation.GetValue(), use_nvdec);
-
+ const bool use_async = Settings::values.use_asynchronous_gpu_emulation.GetValue();
+ auto gpu = std::make_unique<Tegra::GPU>(system, use_async, use_nvdec);
auto context = emu_window.CreateSharedContext();
- const auto scope = context->Acquire();
-
- auto renderer = CreateRenderer(system, emu_window, *gpu, std::move(context));
- if (!renderer->Init()) {
+ auto scope = context->Acquire();
+ try {
+ auto renderer = CreateRenderer(system, emu_window, *gpu, std::move(context));
+ gpu->BindRenderer(std::move(renderer));
+ return gpu;
+ } catch (const std::runtime_error& exception) {
+ LOG_ERROR(HW_GPU, "Failed to initialize GPU: {}", exception.what());
return nullptr;
}
-
- gpu->BindRenderer(std::move(renderer));
- return gpu;
}
u16 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 };
const u32 GuestWarpSize = 32;
/// Handles data specific to a physical device.
-class Device final {
+class Device {
public:
explicit Device(VkInstance instance, vk::PhysicalDevice physical, VkSurfaceKHR surface,
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:
/// Construct an empty handle.
Handle() = default;
+ /// Construct an empty handle.
+ Handle(std::nullptr_t) {}
+
/// Copying Vulkan objects is not supported and will never be.
Handle(const Handle&) = delete;
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() {
emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
- system.Renderer().Rasterizer().LoadDiskResources(
+ system.Renderer().ReadRasterizer()->LoadDiskResources(
system.CurrentProcess()->GetTitleID(), stop_run,
[this](VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total) {
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 @@
#include "core/core.h"
#include "core/settings.h"
#include "ui_configure_graphics.h"
-#include "video_core/renderer_vulkan/renderer_vulkan.h"
+#include "video_core/vulkan_common/vulkan_instance.h"
+#include "video_core/vulkan_common/vulkan_library.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_graphics.h"
@@ -212,11 +213,23 @@ void ConfigureGraphics::UpdateDeviceComboBox() {
ui->device->setEnabled(enabled && !Core::System::GetInstance().IsPoweredOn());
}
-void ConfigureGraphics::RetrieveVulkanDevices() {
+void ConfigureGraphics::RetrieveVulkanDevices() try {
+ using namespace Vulkan;
+
+ vk::InstanceDispatch dld;
+ const Common::DynamicLibrary library = OpenLibrary();
+ const vk::Instance instance = CreateInstance(library, dld, VK_API_VERSION_1_0);
+ const std::vector<VkPhysicalDevice> physical_devices = instance.EnumeratePhysicalDevices();
+
vulkan_devices.clear();
- for (const auto& name : Vulkan::RendererVulkan::EnumerateDevices()) {
+ vulkan_devices.reserve(physical_devices.size());
+ for (const VkPhysicalDevice device : physical_devices) {
+ const char* const name = vk::PhysicalDevice(device, dld).GetProperties().deviceName;
vulkan_devices.push_back(QString::fromStdString(name));
}
+
+} catch (const Vulkan::vk::Exception& exception) {
+ LOG_ERROR(Frontend, "Failed to enumerate devices with error: {}", exception.what());
}
Settings::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) {
// Core is loaded, start the GPU (makes the GPU contexts current to this thread)
system.GPU().Start();
- system.Renderer().Rasterizer().LoadDiskResources(
+ system.Renderer().ReadRasterizer()->LoadDiskResources(
system.CurrentProcess()->GetTitleID(), false,
[](VideoCore::LoadCallbackStage, size_t value, size_t total) {});