summaryrefslogtreecommitdiff
path: root/src/video_core/renderer_vulkan
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-01-05 04:09:39 -0300
committerGravatar ReinUsesLisp2021-02-13 02:16:19 -0300
commit75ccd9959ca7aa78b71fbb800ed2127d8613e9dc (patch)
tree3b9b5c0779cff69ef135bb3394ae70a0d3a9804d /src/video_core/renderer_vulkan
parenttests/buffer_base: Add cached CPU writes tests (diff)
downloadyuzu-75ccd9959ca7aa78b71fbb800ed2127d8613e9dc.tar.gz
yuzu-75ccd9959ca7aa78b71fbb800ed2127d8613e9dc.tar.xz
yuzu-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/video_core/renderer_vulkan')
-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
6 files changed, 91 insertions, 141 deletions
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.