summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/logging/backend.cpp50
-rw-r--r--src/common/logging/backend.h4
-rw-r--r--src/core/hle/service/audio/audren_u.cpp37
-rw-r--r--src/core/hle/service/audio/audren_u.h3
-rw-r--r--src/video_core/CMakeLists.txt2
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.cpp116
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.h87
-rw-r--r--src/web_service/verify_login.h2
-rw-r--r--src/web_service/web_backend.cpp1
-rw-r--r--src/yuzu/compatdb.cpp2
-rw-r--r--src/yuzu/main.cpp5
12 files changed, 268 insertions, 43 deletions
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp
index b369f199f..4462ff3fb 100644
--- a/src/common/logging/backend.cpp
+++ b/src/common/logging/backend.cpp
@@ -39,8 +39,10 @@ public:
39 Impl(Impl const&) = delete; 39 Impl(Impl const&) = delete;
40 const Impl& operator=(Impl const&) = delete; 40 const Impl& operator=(Impl const&) = delete;
41 41
42 void PushEntry(Entry e) { 42 void PushEntry(Class log_class, Level log_level, const char* filename, unsigned int line_num,
43 message_queue.Push(std::move(e)); 43 const char* function, std::string message) {
44 message_queue.Push(
45 CreateEntry(log_class, log_level, filename, line_num, function, std::move(message)));
44 } 46 }
45 47
46 void AddBackend(std::unique_ptr<Backend> backend) { 48 void AddBackend(std::unique_ptr<Backend> backend) {
@@ -108,11 +110,30 @@ private:
108 backend_thread.join(); 110 backend_thread.join();
109 } 111 }
110 112
113 Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr,
114 const char* function, std::string message) const {
115 using std::chrono::duration_cast;
116 using std::chrono::steady_clock;
117
118 Entry entry;
119 entry.timestamp =
120 duration_cast<std::chrono::microseconds>(steady_clock::now() - time_origin);
121 entry.log_class = log_class;
122 entry.log_level = log_level;
123 entry.filename = Common::TrimSourcePath(filename);
124 entry.line_num = line_nr;
125 entry.function = function;
126 entry.message = std::move(message);
127
128 return entry;
129 }
130
111 std::mutex writing_mutex; 131 std::mutex writing_mutex;
112 std::thread backend_thread; 132 std::thread backend_thread;
113 std::vector<std::unique_ptr<Backend>> backends; 133 std::vector<std::unique_ptr<Backend>> backends;
114 Common::MPSCQueue<Log::Entry> message_queue; 134 Common::MPSCQueue<Log::Entry> message_queue;
115 Filter filter; 135 Filter filter;
136 std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()};
116}; 137};
117 138
118void ConsoleBackend::Write(const Entry& entry) { 139void ConsoleBackend::Write(const Entry& entry) {
@@ -271,25 +292,6 @@ const char* GetLevelName(Level log_level) {
271#undef LVL 292#undef LVL
272} 293}
273 294
274Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr,
275 const char* function, std::string message) {
276 using std::chrono::duration_cast;
277 using std::chrono::steady_clock;
278
279 static steady_clock::time_point time_origin = steady_clock::now();
280
281 Entry entry;
282 entry.timestamp = duration_cast<std::chrono::microseconds>(steady_clock::now() - time_origin);
283 entry.log_class = log_class;
284 entry.log_level = log_level;
285 entry.filename = Common::TrimSourcePath(filename);
286 entry.line_num = line_nr;
287 entry.function = function;
288 entry.message = std::move(message);
289
290 return entry;
291}
292
293void SetGlobalFilter(const Filter& filter) { 295void SetGlobalFilter(const Filter& filter) {
294 Impl::Instance().SetGlobalFilter(filter); 296 Impl::Instance().SetGlobalFilter(filter);
295} 297}
@@ -314,9 +316,7 @@ void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
314 if (!filter.CheckMessage(log_class, log_level)) 316 if (!filter.CheckMessage(log_class, log_level))
315 return; 317 return;
316 318
317 Entry entry = 319 instance.PushEntry(log_class, log_level, filename, line_num, function,
318 CreateEntry(log_class, log_level, filename, line_num, function, fmt::vformat(format, args)); 320 fmt::vformat(format, args));
319
320 instance.PushEntry(std::move(entry));
321} 321}
322} // namespace Log 322} // namespace Log
diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h
index a31ee6968..fca0267a1 100644
--- a/src/common/logging/backend.h
+++ b/src/common/logging/backend.h
@@ -135,10 +135,6 @@ const char* GetLogClassName(Class log_class);
135 */ 135 */
136const char* GetLevelName(Level log_level); 136const char* GetLevelName(Level log_level);
137 137
138/// Creates a log entry by formatting the given source location, and message.
139Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr,
140 const char* function, std::string message);
141
142/** 138/**
143 * The global filter will prevent any messages from even being processed if they are filtered. Each 139 * The global filter will prevent any messages from even being processed if they are filtered. Each
144 * backend can have a filter, but if the level is lower than the global filter, the backend will 140 * backend can have a filter, but if the level is lower than the global filter, the backend will
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 49648394c..ea8f9d0bb 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -37,7 +37,7 @@ public:
37 {8, &IAudioRenderer::SetRenderingTimeLimit, "SetRenderingTimeLimit"}, 37 {8, &IAudioRenderer::SetRenderingTimeLimit, "SetRenderingTimeLimit"},
38 {9, &IAudioRenderer::GetRenderingTimeLimit, "GetRenderingTimeLimit"}, 38 {9, &IAudioRenderer::GetRenderingTimeLimit, "GetRenderingTimeLimit"},
39 {10, &IAudioRenderer::RequestUpdateImpl, "RequestUpdateAuto"}, 39 {10, &IAudioRenderer::RequestUpdateImpl, "RequestUpdateAuto"},
40 {11, nullptr, "ExecuteAudioRendererRendering"}, 40 {11, &IAudioRenderer::ExecuteAudioRendererRendering, "ExecuteAudioRendererRendering"},
41 }; 41 };
42 // clang-format on 42 // clang-format on
43 RegisterHandlers(functions); 43 RegisterHandlers(functions);
@@ -138,6 +138,17 @@ private:
138 rb.Push(rendering_time_limit_percent); 138 rb.Push(rendering_time_limit_percent);
139 } 139 }
140 140
141 void ExecuteAudioRendererRendering(Kernel::HLERequestContext& ctx) {
142 LOG_DEBUG(Service_Audio, "called");
143
144 // This service command currently only reports an unsupported operation
145 // error code, or aborts. Given that, we just always return an error
146 // code in this case.
147
148 IPC::ResponseBuilder rb{ctx, 2};
149 rb.Push(ResultCode{ErrorModule::Audio, 201});
150 }
151
141 Kernel::EventPair system_event; 152 Kernel::EventPair system_event;
142 std::unique_ptr<AudioCore::AudioRenderer> renderer; 153 std::unique_ptr<AudioCore::AudioRenderer> renderer;
143 u32 rendering_time_limit_percent = 100; 154 u32 rendering_time_limit_percent = 100;
@@ -235,7 +246,7 @@ AudRenU::AudRenU() : ServiceFramework("audren:u") {
235 {0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"}, 246 {0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"},
236 {1, &AudRenU::GetAudioRendererWorkBufferSize, "GetAudioRendererWorkBufferSize"}, 247 {1, &AudRenU::GetAudioRendererWorkBufferSize, "GetAudioRendererWorkBufferSize"},
237 {2, &AudRenU::GetAudioDeviceService, "GetAudioDeviceService"}, 248 {2, &AudRenU::GetAudioDeviceService, "GetAudioDeviceService"},
238 {3, nullptr, "OpenAudioRendererAuto"}, 249 {3, &AudRenU::OpenAudioRendererAuto, "OpenAudioRendererAuto"},
239 {4, &AudRenU::GetAudioDeviceServiceWithRevisionInfo, "GetAudioDeviceServiceWithRevisionInfo"}, 250 {4, &AudRenU::GetAudioDeviceServiceWithRevisionInfo, "GetAudioDeviceServiceWithRevisionInfo"},
240 }; 251 };
241 // clang-format on 252 // clang-format on
@@ -248,12 +259,7 @@ AudRenU::~AudRenU() = default;
248void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) { 259void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) {
249 LOG_DEBUG(Service_Audio, "called"); 260 LOG_DEBUG(Service_Audio, "called");
250 261
251 IPC::RequestParser rp{ctx}; 262 OpenAudioRendererImpl(ctx);
252 auto params = rp.PopRaw<AudioCore::AudioRendererParameter>();
253 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
254
255 rb.Push(RESULT_SUCCESS);
256 rb.PushIpcInterface<Audio::IAudioRenderer>(std::move(params));
257} 263}
258 264
259void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) { 265void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
@@ -325,6 +331,12 @@ void AudRenU::GetAudioDeviceService(Kernel::HLERequestContext& ctx) {
325 rb.PushIpcInterface<Audio::IAudioDevice>(); 331 rb.PushIpcInterface<Audio::IAudioDevice>();
326} 332}
327 333
334void AudRenU::OpenAudioRendererAuto(Kernel::HLERequestContext& ctx) {
335 LOG_DEBUG(Service_Audio, "called");
336
337 OpenAudioRendererImpl(ctx);
338}
339
328void AudRenU::GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx) { 340void AudRenU::GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx) {
329 LOG_WARNING(Service_Audio, "(STUBBED) called"); 341 LOG_WARNING(Service_Audio, "(STUBBED) called");
330 342
@@ -335,6 +347,15 @@ void AudRenU::GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& c
335 // based on the current revision 347 // based on the current revision
336} 348}
337 349
350void AudRenU::OpenAudioRendererImpl(Kernel::HLERequestContext& ctx) {
351 IPC::RequestParser rp{ctx};
352 const auto params = rp.PopRaw<AudioCore::AudioRendererParameter>();
353 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
354
355 rb.Push(RESULT_SUCCESS);
356 rb.PushIpcInterface<IAudioRenderer>(params);
357}
358
338bool AudRenU::IsFeatureSupported(AudioFeatures feature, u32_le revision) const { 359bool AudRenU::IsFeatureSupported(AudioFeatures feature, u32_le revision) const {
339 u32_be version_num = (revision - Common::MakeMagic('R', 'E', 'V', '0')); // Byte swap 360 u32_be version_num = (revision - Common::MakeMagic('R', 'E', 'V', '0')); // Byte swap
340 switch (feature) { 361 switch (feature) {
diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h
index 3d63388fb..e55d25973 100644
--- a/src/core/hle/service/audio/audren_u.h
+++ b/src/core/hle/service/audio/audren_u.h
@@ -21,8 +21,11 @@ private:
21 void OpenAudioRenderer(Kernel::HLERequestContext& ctx); 21 void OpenAudioRenderer(Kernel::HLERequestContext& ctx);
22 void GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx); 22 void GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx);
23 void GetAudioDeviceService(Kernel::HLERequestContext& ctx); 23 void GetAudioDeviceService(Kernel::HLERequestContext& ctx);
24 void OpenAudioRendererAuto(Kernel::HLERequestContext& ctx);
24 void GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx); 25 void GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx);
25 26
27 void OpenAudioRendererImpl(Kernel::HLERequestContext& ctx);
28
26 enum class AudioFeatures : u32 { 29 enum class AudioFeatures : u32 {
27 Splitter, 30 Splitter,
28 }; 31 };
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 60529323e..3e9d2b3be 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -104,6 +104,8 @@ add_library(video_core STATIC
104if (ENABLE_VULKAN) 104if (ENABLE_VULKAN)
105 target_sources(video_core PRIVATE 105 target_sources(video_core PRIVATE
106 renderer_vulkan/declarations.h 106 renderer_vulkan/declarations.h
107 renderer_vulkan/vk_buffer_cache.cpp
108 renderer_vulkan/vk_buffer_cache.h
107 renderer_vulkan/vk_device.cpp 109 renderer_vulkan/vk_device.cpp
108 renderer_vulkan/vk_device.h 110 renderer_vulkan/vk_device.h
109 renderer_vulkan/vk_memory_manager.cpp 111 renderer_vulkan/vk_memory_manager.cpp
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 5fdf1164d..b5a9722f9 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -966,7 +966,7 @@ Surface RasterizerCacheOpenGL::GetColorBufferSurface(std::size_t index, bool pre
966 const auto& regs{gpu.regs}; 966 const auto& regs{gpu.regs};
967 967
968 if (!gpu.dirty_flags.color_buffer[index]) { 968 if (!gpu.dirty_flags.color_buffer[index]) {
969 return last_color_buffers[index]; 969 return current_color_buffers[index];
970 } 970 }
971 gpu.dirty_flags.color_buffer.reset(index); 971 gpu.dirty_flags.color_buffer.reset(index);
972 972
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
new file mode 100644
index 000000000..18b7b94a1
--- /dev/null
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
@@ -0,0 +1,116 @@
1// Copyright 2019 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <cstring>
6#include <memory>
7#include <optional>
8#include <tuple>
9
10#include "common/alignment.h"
11#include "core/core.h"
12#include "core/memory.h"
13#include "video_core/renderer_vulkan/declarations.h"
14#include "video_core/renderer_vulkan/vk_buffer_cache.h"
15#include "video_core/renderer_vulkan/vk_scheduler.h"
16#include "video_core/renderer_vulkan/vk_stream_buffer.h"
17
18namespace Vulkan {
19
20VKBufferCache::VKBufferCache(Tegra::MemoryManager& tegra_memory_manager,
21 VideoCore::RasterizerInterface& rasterizer, const VKDevice& device,
22 VKMemoryManager& memory_manager, VKScheduler& scheduler, u64 size)
23 : RasterizerCache{rasterizer}, tegra_memory_manager{tegra_memory_manager} {
24 const auto usage = vk::BufferUsageFlagBits::eVertexBuffer |
25 vk::BufferUsageFlagBits::eIndexBuffer |
26 vk::BufferUsageFlagBits::eUniformBuffer;
27 const auto access = vk::AccessFlagBits::eVertexAttributeRead | vk::AccessFlagBits::eIndexRead |
28 vk::AccessFlagBits::eUniformRead;
29 stream_buffer =
30 std::make_unique<VKStreamBuffer>(device, memory_manager, scheduler, size, usage, access,
31 vk::PipelineStageFlagBits::eAllCommands);
32 buffer_handle = stream_buffer->GetBuffer();
33}
34
35VKBufferCache::~VKBufferCache() = default;
36
37u64 VKBufferCache::UploadMemory(Tegra::GPUVAddr gpu_addr, std::size_t size, u64 alignment,
38 bool cache) {
39 const auto cpu_addr{tegra_memory_manager.GpuToCpuAddress(gpu_addr)};
40 ASSERT(cpu_addr);
41
42 // Cache management is a big overhead, so only cache entries with a given size.
43 // TODO: Figure out which size is the best for given games.
44 cache &= size >= 2048;
45
46 if (cache) {
47 if (auto entry = TryGet(*cpu_addr); entry) {
48 if (entry->size >= size && entry->alignment == alignment) {
49 return entry->offset;
50 }
51 Unregister(entry);
52 }
53 }
54
55 AlignBuffer(alignment);
56 const u64 uploaded_offset = buffer_offset;
57
58 Memory::ReadBlock(*cpu_addr, buffer_ptr, size);
59
60 buffer_ptr += size;
61 buffer_offset += size;
62
63 if (cache) {
64 auto entry = std::make_shared<CachedBufferEntry>();
65 entry->offset = uploaded_offset;
66 entry->size = size;
67 entry->alignment = alignment;
68 entry->addr = *cpu_addr;
69 Register(entry);
70 }
71
72 return uploaded_offset;
73}
74
75u64 VKBufferCache::UploadHostMemory(const u8* raw_pointer, std::size_t size, u64 alignment) {
76 AlignBuffer(alignment);
77 std::memcpy(buffer_ptr, raw_pointer, size);
78 const u64 uploaded_offset = buffer_offset;
79
80 buffer_ptr += size;
81 buffer_offset += size;
82 return uploaded_offset;
83}
84
85std::tuple<u8*, u64> VKBufferCache::ReserveMemory(std::size_t size, u64 alignment) {
86 AlignBuffer(alignment);
87 u8* const uploaded_ptr = buffer_ptr;
88 const u64 uploaded_offset = buffer_offset;
89
90 buffer_ptr += size;
91 buffer_offset += size;
92 return {uploaded_ptr, uploaded_offset};
93}
94
95void VKBufferCache::Reserve(std::size_t max_size) {
96 bool invalidate;
97 std::tie(buffer_ptr, buffer_offset_base, invalidate) = stream_buffer->Reserve(max_size);
98 buffer_offset = buffer_offset_base;
99
100 if (invalidate) {
101 InvalidateAll();
102 }
103}
104
105VKExecutionContext VKBufferCache::Send(VKExecutionContext exctx) {
106 return stream_buffer->Send(exctx, buffer_offset - buffer_offset_base);
107}
108
109void VKBufferCache::AlignBuffer(std::size_t alignment) {
110 // Align the offset, not the mapped pointer
111 const u64 offset_aligned = Common::AlignUp(buffer_offset, alignment);
112 buffer_ptr += offset_aligned - buffer_offset;
113 buffer_offset = offset_aligned;
114}
115
116} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h
new file mode 100644
index 000000000..d8e916f31
--- /dev/null
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h
@@ -0,0 +1,87 @@
1// Copyright 2019 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8#include <tuple>
9
10#include "common/common_types.h"
11#include "video_core/gpu.h"
12#include "video_core/rasterizer_cache.h"
13#include "video_core/renderer_vulkan/declarations.h"
14#include "video_core/renderer_vulkan/vk_scheduler.h"
15
16namespace Tegra {
17class MemoryManager;
18}
19
20namespace Vulkan {
21
22class VKDevice;
23class VKFence;
24class VKMemoryManager;
25class VKStreamBuffer;
26
27struct CachedBufferEntry final : public RasterizerCacheObject {
28 VAddr GetAddr() const override {
29 return addr;
30 }
31
32 std::size_t GetSizeInBytes() const override {
33 return size;
34 }
35
36 // We do not have to flush this cache as things in it are never modified by us.
37 void Flush() override {}
38
39 VAddr addr;
40 std::size_t size;
41 u64 offset;
42 std::size_t alignment;
43};
44
45class VKBufferCache final : public RasterizerCache<std::shared_ptr<CachedBufferEntry>> {
46public:
47 explicit VKBufferCache(Tegra::MemoryManager& tegra_memory_manager,
48 VideoCore::RasterizerInterface& rasterizer, const VKDevice& device,
49 VKMemoryManager& memory_manager, VKScheduler& scheduler, u64 size);
50 ~VKBufferCache();
51
52 /// Uploads data from a guest GPU address. Returns host's buffer offset where it's been
53 /// allocated.
54 u64 UploadMemory(Tegra::GPUVAddr gpu_addr, std::size_t size, u64 alignment = 4,
55 bool cache = true);
56
57 /// Uploads from a host memory. Returns host's buffer offset where it's been allocated.
58 u64 UploadHostMemory(const u8* raw_pointer, std::size_t size, u64 alignment = 4);
59
60 /// Reserves memory to be used by host's CPU. Returns mapped address and offset.
61 std::tuple<u8*, u64> ReserveMemory(std::size_t size, u64 alignment = 4);
62
63 /// Reserves a region of memory to be used in subsequent upload/reserve operations.
64 void Reserve(std::size_t max_size);
65
66 /// Ensures that the set data is sent to the device.
67 [[nodiscard]] VKExecutionContext Send(VKExecutionContext exctx);
68
69 /// Returns the buffer cache handle.
70 vk::Buffer GetBuffer() const {
71 return buffer_handle;
72 }
73
74private:
75 void AlignBuffer(std::size_t alignment);
76
77 Tegra::MemoryManager& tegra_memory_manager;
78
79 std::unique_ptr<VKStreamBuffer> stream_buffer;
80 vk::Buffer buffer_handle;
81
82 u8* buffer_ptr = nullptr;
83 u64 buffer_offset = 0;
84 u64 buffer_offset_base = 0;
85};
86
87} // namespace Vulkan
diff --git a/src/web_service/verify_login.h b/src/web_service/verify_login.h
index 39db32dbb..821b345d7 100644
--- a/src/web_service/verify_login.h
+++ b/src/web_service/verify_login.h
@@ -4,8 +4,6 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <functional>
8#include <future>
9#include <string> 7#include <string>
10 8
11namespace WebService { 9namespace WebService {
diff --git a/src/web_service/web_backend.cpp b/src/web_service/web_backend.cpp
index b7737b615..40da1a4e2 100644
--- a/src/web_service/web_backend.cpp
+++ b/src/web_service/web_backend.cpp
@@ -10,7 +10,6 @@
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "common/logging/log.h" 11#include "common/logging/log.h"
12#include "common/web_result.h" 12#include "common/web_result.h"
13#include "core/settings.h"
14#include "web_service/web_backend.h" 13#include "web_service/web_backend.h"
15 14
16namespace WebService { 15namespace WebService {
diff --git a/src/yuzu/compatdb.cpp b/src/yuzu/compatdb.cpp
index 5f0896f84..c09a06520 100644
--- a/src/yuzu/compatdb.cpp
+++ b/src/yuzu/compatdb.cpp
@@ -61,7 +61,7 @@ void CompatDB::Submit() {
61 button(QWizard::CancelButton)->setVisible(false); 61 button(QWizard::CancelButton)->setVisible(false);
62 62
63 testcase_watcher.setFuture(QtConcurrent::run( 63 testcase_watcher.setFuture(QtConcurrent::run(
64 [this]() { return Core::System::GetInstance().TelemetrySession().SubmitTestcase(); })); 64 [] { return Core::System::GetInstance().TelemetrySession().SubmitTestcase(); }));
65 break; 65 break;
66 default: 66 default:
67 LOG_ERROR(Frontend, "Unexpected page: {}", currentId()); 67 LOG_ERROR(Frontend, "Unexpected page: {}", currentId());
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 1d460c189..5ab7896d4 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -561,7 +561,10 @@ void GMainWindow::InitializeHotkeys() {
561 Settings::values.use_frame_limit = !Settings::values.use_frame_limit; 561 Settings::values.use_frame_limit = !Settings::values.use_frame_limit;
562 UpdateStatusBar(); 562 UpdateStatusBar();
563 }); 563 });
564 constexpr u16 SPEED_LIMIT_STEP = 5; 564 // TODO: Remove this comment/static whenever the next major release of
565 // MSVC occurs and we make it a requirement (see:
566 // https://developercommunity.visualstudio.com/content/problem/93922/constexprs-are-trying-to-be-captured-in-lambda-fun.html)
567 static constexpr u16 SPEED_LIMIT_STEP = 5;
565 connect(hotkey_registry.GetHotkey("Main Window", "Increase Speed Limit", this), 568 connect(hotkey_registry.GetHotkey("Main Window", "Increase Speed Limit", this),
566 &QShortcut::activated, this, [&] { 569 &QShortcut::activated, this, [&] {
567 if (Settings::values.frame_limit < 9999 - SPEED_LIMIT_STEP) { 570 if (Settings::values.frame_limit < 9999 - SPEED_LIMIT_STEP) {