summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/settings.cpp2
-rw-r--r--src/common/settings.h10
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp85
-rw-r--r--src/input_common/mouse/mouse_poller.cpp2
-rw-r--r--src/video_core/command_classes/vic.cpp21
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp8
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.cpp5
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp6
-rw-r--r--src/yuzu/bootmanager.cpp9
-rw-r--r--src/yuzu/configuration/config.cpp25
-rw-r--r--src/yuzu/configuration/configure_audio.cpp13
-rw-r--r--src/yuzu/configuration/configure_graphics.cpp18
-rw-r--r--src/yuzu/configuration/configure_input_advanced.ui15
-rw-r--r--src/yuzu_cmd/config.cpp6
-rw-r--r--src/yuzu_cmd/default_ini.h4
15 files changed, 99 insertions, 130 deletions
diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index e1973af85..bf5514386 100644
--- a/src/common/settings.cpp
+++ b/src/common/settings.cpp
@@ -103,7 +103,7 @@ float Volume() {
103 if (values.audio_muted) { 103 if (values.audio_muted) {
104 return 0.0f; 104 return 0.0f;
105 } 105 }
106 return values.volume.GetValue(); 106 return values.volume.GetValue() / 100.0f;
107} 107}
108 108
109void RestoreGlobalState(bool is_powered_on) { 109void RestoreGlobalState(bool is_powered_on) {
diff --git a/src/common/settings.h b/src/common/settings.h
index 71d0f864f..ce1bc647d 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -278,7 +278,7 @@ struct Values {
278 BasicSetting<std::string> sink_id{"auto", "output_engine"}; 278 BasicSetting<std::string> sink_id{"auto", "output_engine"};
279 BasicSetting<bool> audio_muted{false, "audio_muted"}; 279 BasicSetting<bool> audio_muted{false, "audio_muted"};
280 Setting<bool> enable_audio_stretching{true, "enable_audio_stretching"}; 280 Setting<bool> enable_audio_stretching{true, "enable_audio_stretching"};
281 Setting<float> volume{1.0f, "volume"}; 281 Setting<u8> volume{100, "volume"};
282 282
283 // Core 283 // Core
284 Setting<bool> use_multi_core{true, "use_multi_core"}; 284 Setting<bool> use_multi_core{true, "use_multi_core"};
@@ -336,9 +336,9 @@ struct Values {
336 Setting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"}; 336 Setting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"};
337 Setting<bool> use_caches_gc{false, "use_caches_gc"}; 337 Setting<bool> use_caches_gc{false, "use_caches_gc"};
338 338
339 Setting<float> bg_red{0.0f, "bg_red"}; 339 Setting<u8> bg_red{0, "bg_red"};
340 Setting<float> bg_green{0.0f, "bg_green"}; 340 Setting<u8> bg_green{0, "bg_green"};
341 Setting<float> bg_blue{0.0f, "bg_blue"}; 341 Setting<u8> bg_blue{0, "bg_blue"};
342 342
343 // System 343 // System
344 Setting<std::optional<u32>> rng_seed{std::optional<u32>(), "rng_seed"}; 344 Setting<std::optional<u32>> rng_seed{std::optional<u32>(), "rng_seed"};
@@ -368,7 +368,7 @@ struct Values {
368 "udp_input_servers"}; 368 "udp_input_servers"};
369 369
370 BasicSetting<bool> mouse_panning{false, "mouse_panning"}; 370 BasicSetting<bool> mouse_panning{false, "mouse_panning"};
371 BasicSetting<float> mouse_panning_sensitivity{1.0f, "mouse_panning_sensitivity"}; 371 BasicSetting<u8> mouse_panning_sensitivity{10, "mouse_panning_sensitivity"};
372 BasicSetting<bool> mouse_enabled{false, "mouse_enabled"}; 372 BasicSetting<bool> mouse_enabled{false, "mouse_enabled"};
373 std::string mouse_device; 373 std::string mouse_device;
374 MouseButtonsRaw mouse_buttons; 374 MouseButtonsRaw mouse_buttons;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
index 98e6296f1..1403a39d0 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
@@ -19,26 +19,29 @@
19namespace Service::Nvidia::Devices { 19namespace Service::Nvidia::Devices {
20 20
21namespace { 21namespace {
22// Splice vectors will copy count amount of type T from the input vector into the dst vector. 22// Copies count amount of type T from the input vector into the dst vector.
23// Returns the number of bytes written into dst.
23template <typename T> 24template <typename T>
24std::size_t SpliceVectors(const std::vector<u8>& input, std::vector<T>& dst, std::size_t count, 25std::size_t SliceVectors(const std::vector<u8>& input, std::vector<T>& dst, std::size_t count,
25 std::size_t offset) { 26 std::size_t offset) {
26 if (!dst.empty()) { 27 if (dst.empty()) {
27 std::memcpy(dst.data(), input.data() + offset, count * sizeof(T)); 28 return 0;
28 } 29 }
29 return 0; 30 const size_t bytes_copied = count * sizeof(T);
31 std::memcpy(dst.data(), input.data() + offset, bytes_copied);
32 return bytes_copied;
30} 33}
31 34
32// Write vectors will write data to the output buffer 35// Writes the data in src to an offset into the dst vector. The offset is specified in bytes
36// Returns the number of bytes written into dst.
33template <typename T> 37template <typename T>
34std::size_t WriteVectors(std::vector<u8>& dst, const std::vector<T>& src, std::size_t offset) { 38std::size_t WriteVectors(std::vector<u8>& dst, const std::vector<T>& src, std::size_t offset) {
35 if (src.empty()) { 39 if (src.empty()) {
36 return 0; 40 return 0;
37 } else {
38 std::memcpy(dst.data() + offset, src.data(), src.size() * sizeof(T));
39 offset += src.size() * sizeof(T);
40 return offset;
41 } 41 }
42 const size_t bytes_copied = src.size() * sizeof(T);
43 std::memcpy(dst.data() + offset, src.data(), bytes_copied);
44 return bytes_copied;
42} 45}
43} // Anonymous namespace 46} // Anonymous namespace
44 47
@@ -62,7 +65,6 @@ NvResult nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u
62 LOG_DEBUG(Service_NVDRV, "called NVDEC Submit, cmd_buffer_count={}", params.cmd_buffer_count); 65 LOG_DEBUG(Service_NVDRV, "called NVDEC Submit, cmd_buffer_count={}", params.cmd_buffer_count);
63 66
64 // Instantiate param buffers 67 // Instantiate param buffers
65 std::size_t offset = sizeof(IoctlSubmit);
66 std::vector<CommandBuffer> command_buffers(params.cmd_buffer_count); 68 std::vector<CommandBuffer> command_buffers(params.cmd_buffer_count);
67 std::vector<Reloc> relocs(params.relocation_count); 69 std::vector<Reloc> relocs(params.relocation_count);
68 std::vector<u32> reloc_shifts(params.relocation_count); 70 std::vector<u32> reloc_shifts(params.relocation_count);
@@ -70,13 +72,14 @@ NvResult nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u
70 std::vector<SyncptIncr> wait_checks(params.syncpoint_count); 72 std::vector<SyncptIncr> wait_checks(params.syncpoint_count);
71 std::vector<Fence> fences(params.fence_count); 73 std::vector<Fence> fences(params.fence_count);
72 74
73 // Splice input into their respective buffers 75 // Slice input into their respective buffers
74 offset = SpliceVectors(input, command_buffers, params.cmd_buffer_count, offset); 76 std::size_t offset = sizeof(IoctlSubmit);
75 offset = SpliceVectors(input, relocs, params.relocation_count, offset); 77 offset += SliceVectors(input, command_buffers, params.cmd_buffer_count, offset);
76 offset = SpliceVectors(input, reloc_shifts, params.relocation_count, offset); 78 offset += SliceVectors(input, relocs, params.relocation_count, offset);
77 offset = SpliceVectors(input, syncpt_increments, params.syncpoint_count, offset); 79 offset += SliceVectors(input, reloc_shifts, params.relocation_count, offset);
78 offset = SpliceVectors(input, wait_checks, params.syncpoint_count, offset); 80 offset += SliceVectors(input, syncpt_increments, params.syncpoint_count, offset);
79 offset = SpliceVectors(input, fences, params.fence_count, offset); 81 offset += SliceVectors(input, wait_checks, params.syncpoint_count, offset);
82 offset += SliceVectors(input, fences, params.fence_count, offset);
80 83
81 auto& gpu = system.GPU(); 84 auto& gpu = system.GPU();
82 if (gpu.UseNvdec()) { 85 if (gpu.UseNvdec()) {
@@ -88,35 +91,27 @@ NvResult nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u
88 } 91 }
89 } 92 }
90 for (const auto& cmd_buffer : command_buffers) { 93 for (const auto& cmd_buffer : command_buffers) {
91 auto object = nvmap_dev->GetObject(cmd_buffer.memory_id); 94 const auto object = nvmap_dev->GetObject(cmd_buffer.memory_id);
92 ASSERT_OR_EXECUTE(object, return NvResult::InvalidState;); 95 ASSERT_OR_EXECUTE(object, return NvResult::InvalidState;);
93 const auto map = FindBufferMap(object->dma_map_addr);
94 if (!map) {
95 LOG_ERROR(Service_NVDRV, "Tried to submit an invalid offset 0x{:X} dma 0x{:X}",
96 object->addr, object->dma_map_addr);
97 return NvResult::Success;
98 }
99 Tegra::ChCommandHeaderList cmdlist(cmd_buffer.word_count); 96 Tegra::ChCommandHeaderList cmdlist(cmd_buffer.word_count);
100 gpu.MemoryManager().ReadBlock(map->StartAddr() + cmd_buffer.offset, cmdlist.data(), 97 system.Memory().ReadBlock(object->addr + cmd_buffer.offset, cmdlist.data(),
101 cmdlist.size() * sizeof(u32)); 98 cmdlist.size() * sizeof(u32));
102 gpu.PushCommandBuffer(cmdlist); 99 gpu.PushCommandBuffer(cmdlist);
103 } 100 }
104 if (gpu.UseNvdec()) { 101 if (gpu.UseNvdec()) {
105
106 fences[0].value = syncpoint_manager.IncreaseSyncpoint(fences[0].id, 1); 102 fences[0].value = syncpoint_manager.IncreaseSyncpoint(fences[0].id, 1);
107
108 Tegra::ChCommandHeaderList cmdlist{{(4 << 28) | fences[0].id}}; 103 Tegra::ChCommandHeaderList cmdlist{{(4 << 28) | fences[0].id}};
109 gpu.PushCommandBuffer(cmdlist); 104 gpu.PushCommandBuffer(cmdlist);
110 } 105 }
111 std::memcpy(output.data(), &params, sizeof(IoctlSubmit)); 106 std::memcpy(output.data(), &params, sizeof(IoctlSubmit));
112 // Some games expect command_buffers to be written back 107 // Some games expect command_buffers to be written back
113 offset = sizeof(IoctlSubmit); 108 offset = sizeof(IoctlSubmit);
114 offset = WriteVectors(output, command_buffers, offset); 109 offset += WriteVectors(output, command_buffers, offset);
115 offset = WriteVectors(output, relocs, offset); 110 offset += WriteVectors(output, relocs, offset);
116 offset = WriteVectors(output, reloc_shifts, offset); 111 offset += WriteVectors(output, reloc_shifts, offset);
117 offset = WriteVectors(output, syncpt_increments, offset); 112 offset += WriteVectors(output, syncpt_increments, offset);
118 offset = WriteVectors(output, wait_checks, offset); 113 offset += WriteVectors(output, wait_checks, offset);
119 offset = WriteVectors(output, fences, offset); 114 offset += WriteVectors(output, fences, offset);
120 115
121 return NvResult::Success; 116 return NvResult::Success;
122} 117}
@@ -148,14 +143,14 @@ NvResult nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vecto
148 std::memcpy(&params, input.data(), sizeof(IoctlMapBuffer)); 143 std::memcpy(&params, input.data(), sizeof(IoctlMapBuffer));
149 std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); 144 std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries);
150 145
151 SpliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer)); 146 SliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer));
152 147
153 auto& gpu = system.GPU(); 148 auto& gpu = system.GPU();
154 149
155 for (auto& cmf_buff : cmd_buffer_handles) { 150 for (auto& cmd_buffer : cmd_buffer_handles) {
156 auto object{nvmap_dev->GetObject(cmf_buff.map_handle)}; 151 auto object{nvmap_dev->GetObject(cmd_buffer.map_handle)};
157 if (!object) { 152 if (!object) {
158 LOG_ERROR(Service_NVDRV, "invalid cmd_buffer nvmap_handle={:X}", cmf_buff.map_handle); 153 LOG_ERROR(Service_NVDRV, "invalid cmd_buffer nvmap_handle={:X}", cmd_buffer.map_handle);
159 std::memcpy(output.data(), &params, output.size()); 154 std::memcpy(output.data(), &params, output.size());
160 return NvResult::InvalidState; 155 return NvResult::InvalidState;
161 } 156 }
@@ -170,7 +165,7 @@ NvResult nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vecto
170 if (!object->dma_map_addr) { 165 if (!object->dma_map_addr) {
171 LOG_ERROR(Service_NVDRV, "failed to map size={}", object->size); 166 LOG_ERROR(Service_NVDRV, "failed to map size={}", object->size);
172 } else { 167 } else {
173 cmf_buff.map_address = object->dma_map_addr; 168 cmd_buffer.map_address = object->dma_map_addr;
174 AddBufferMap(object->dma_map_addr, object->size, object->addr, 169 AddBufferMap(object->dma_map_addr, object->size, object->addr,
175 object->status == nvmap::Object::Status::Allocated); 170 object->status == nvmap::Object::Status::Allocated);
176 } 171 }
@@ -186,14 +181,14 @@ NvResult nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vec
186 IoctlMapBuffer params{}; 181 IoctlMapBuffer params{};
187 std::memcpy(&params, input.data(), sizeof(IoctlMapBuffer)); 182 std::memcpy(&params, input.data(), sizeof(IoctlMapBuffer));
188 std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); 183 std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries);
189 SpliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer)); 184 SliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer));
190 185
191 auto& gpu = system.GPU(); 186 auto& gpu = system.GPU();
192 187
193 for (auto& cmf_buff : cmd_buffer_handles) { 188 for (auto& cmd_buffer : cmd_buffer_handles) {
194 const auto object{nvmap_dev->GetObject(cmf_buff.map_handle)}; 189 const auto object{nvmap_dev->GetObject(cmd_buffer.map_handle)};
195 if (!object) { 190 if (!object) {
196 LOG_ERROR(Service_NVDRV, "invalid cmd_buffer nvmap_handle={:X}", cmf_buff.map_handle); 191 LOG_ERROR(Service_NVDRV, "invalid cmd_buffer nvmap_handle={:X}", cmd_buffer.map_handle);
197 std::memcpy(output.data(), &params, output.size()); 192 std::memcpy(output.data(), &params, output.size());
198 return NvResult::InvalidState; 193 return NvResult::InvalidState;
199 } 194 }
diff --git a/src/input_common/mouse/mouse_poller.cpp b/src/input_common/mouse/mouse_poller.cpp
index 45b3d7340..efcdd85d2 100644
--- a/src/input_common/mouse/mouse_poller.cpp
+++ b/src/input_common/mouse/mouse_poller.cpp
@@ -84,7 +84,7 @@ public:
84 std::lock_guard lock{mutex}; 84 std::lock_guard lock{mutex};
85 const auto axis_value = 85 const auto axis_value =
86 static_cast<float>(mouse_input->GetMouseState(button).axis.at(axis)); 86 static_cast<float>(mouse_input->GetMouseState(button).axis.at(axis));
87 const float sensitivity = Settings::values.mouse_panning_sensitivity.GetValue(); 87 const float sensitivity = Settings::values.mouse_panning_sensitivity.GetValue() * 0.10f;
88 return axis_value * sensitivity / (100.0f * range); 88 return axis_value * sensitivity / (100.0f * range);
89 } 89 }
90 90
diff --git a/src/video_core/command_classes/vic.cpp b/src/video_core/command_classes/vic.cpp
index ff3db0aee..ffb7c82a1 100644
--- a/src/video_core/command_classes/vic.cpp
+++ b/src/video_core/command_classes/vic.cpp
@@ -129,28 +129,27 @@ void Vic::Execute() {
129 129
130 const std::size_t surface_width = config.surface_width_minus1 + 1; 130 const std::size_t surface_width = config.surface_width_minus1 + 1;
131 const std::size_t surface_height = config.surface_height_minus1 + 1; 131 const std::size_t surface_height = config.surface_height_minus1 + 1;
132 const std::size_t half_width = surface_width / 2; 132 const auto frame_width = std::min(surface_width, static_cast<size_t>(frame->width));
133 const std::size_t half_height = config.surface_height_minus1 / 2; 133 const auto frame_height = std::min(surface_height, static_cast<size_t>(frame->height));
134 const std::size_t half_width = frame_width / 2;
135 const std::size_t half_height = frame_height / 2;
134 const std::size_t aligned_width = (surface_width + 0xff) & ~0xff; 136 const std::size_t aligned_width = (surface_width + 0xff) & ~0xff;
135 137
136 const auto* luma_ptr = frame->data[0]; 138 const auto* luma_ptr = frame->data[0];
137 const auto* chroma_b_ptr = frame->data[1]; 139 const auto* chroma_b_ptr = frame->data[1];
138 const auto* chroma_r_ptr = frame->data[2]; 140 const auto* chroma_r_ptr = frame->data[2];
139 const auto stride = frame->linesize[0]; 141 const auto stride = static_cast<size_t>(frame->linesize[0]);
140 const auto half_stride = frame->linesize[1]; 142 const auto half_stride = static_cast<size_t>(frame->linesize[1]);
141 143
142 luma_buffer.resize(aligned_width * surface_height); 144 luma_buffer.resize(aligned_width * surface_height);
143 chroma_buffer.resize(aligned_width * half_height); 145 chroma_buffer.resize(aligned_width * surface_height / 2);
144 146
145 // Populate luma buffer 147 // Populate luma buffer
146 for (std::size_t y = 0; y < surface_height - 1; ++y) { 148 for (std::size_t y = 0; y < frame_height; ++y) {
147 const std::size_t src = y * stride; 149 const std::size_t src = y * stride;
148 const std::size_t dst = y * aligned_width; 150 const std::size_t dst = y * aligned_width;
149 151 for (std::size_t x = 0; x < frame_width; ++x) {
150 const std::size_t size = surface_width; 152 luma_buffer[dst + x] = luma_ptr[src + x];
151
152 for (std::size_t offset = 0; offset < size; ++offset) {
153 luma_buffer[dst + offset] = luma_ptr[src + offset];
154 } 153 }
155 } 154 }
156 gpu.MemoryManager().WriteBlock(output_surface_luma_address, luma_buffer.data(), 155 gpu.MemoryManager().WriteBlock(output_surface_luma_address, luma_buffer.data(),
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index a718bff7a..c12929de6 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -229,9 +229,6 @@ void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color
229} 229}
230 230
231void RendererOpenGL::InitOpenGLObjects() { 231void RendererOpenGL::InitOpenGLObjects() {
232 glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(),
233 Settings::values.bg_blue.GetValue(), 0.0f);
234
235 // Create shader programs 232 // Create shader programs
236 OGLShader vertex_shader; 233 OGLShader vertex_shader;
237 vertex_shader.Create(HostShaders::OPENGL_PRESENT_VERT, GL_VERTEX_SHADER); 234 vertex_shader.Create(HostShaders::OPENGL_PRESENT_VERT, GL_VERTEX_SHADER);
@@ -337,8 +334,9 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
337void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { 334void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
338 if (renderer_settings.set_background_color) { 335 if (renderer_settings.set_background_color) {
339 // Update background color before drawing 336 // Update background color before drawing
340 glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(), 337 glClearColor(Settings::values.bg_red.GetValue() / 255.0f,
341 Settings::values.bg_blue.GetValue(), 0.0f); 338 Settings::values.bg_green.GetValue() / 255.0f,
339 Settings::values.bg_blue.GetValue() / 255.0f, 1.0f);
342 } 340 }
343 341
344 // Set projection matrix 342 // Set projection matrix
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
index a1a32aabe..363134129 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
@@ -225,8 +225,11 @@ VkSemaphore VKBlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer, bool
225 descriptor_set = descriptor_sets[image_index], buffer = *buffer, 225 descriptor_set = descriptor_sets[image_index], buffer = *buffer,
226 size = swapchain.GetSize(), pipeline = *pipeline, 226 size = swapchain.GetSize(), pipeline = *pipeline,
227 layout = *pipeline_layout](vk::CommandBuffer cmdbuf) { 227 layout = *pipeline_layout](vk::CommandBuffer cmdbuf) {
228 const f32 bg_red = Settings::values.bg_red.GetValue() / 255.0f;
229 const f32 bg_green = Settings::values.bg_green.GetValue() / 255.0f;
230 const f32 bg_blue = Settings::values.bg_blue.GetValue() / 255.0f;
228 const VkClearValue clear_color{ 231 const VkClearValue clear_color{
229 .color = {.float32 = {0.0f, 0.0f, 0.0f, 0.0f}}, 232 .color = {.float32 = {bg_red, bg_green, bg_blue, 1.0f}},
230 }; 233 };
231 const VkRenderPassBeginInfo renderpass_bi{ 234 const VkRenderPassBeginInfo renderpass_bi{
232 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 235 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index e378a5679..a8ffbe6ba 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -357,11 +357,13 @@ void RasterizerVulkan::Clear() {
357 .height = std::min(clear_rect.rect.extent.height, render_area.height), 357 .height = std::min(clear_rect.rect.extent.height, render_area.height),
358 }; 358 };
359 359
360 if (use_color) { 360 const u32 color_attachment = regs.clear_buffers.RT;
361 const auto attachment_aspect_mask = framebuffer->ImageRanges()[color_attachment].aspectMask;
362 const bool is_color_rt = (attachment_aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != 0;
363 if (use_color && is_color_rt) {
361 VkClearValue clear_value; 364 VkClearValue clear_value;
362 std::memcpy(clear_value.color.float32, regs.clear_color, sizeof(regs.clear_color)); 365 std::memcpy(clear_value.color.float32, regs.clear_color, sizeof(regs.clear_color));
363 366
364 const u32 color_attachment = regs.clear_buffers.RT;
365 scheduler.Record([color_attachment, clear_value, clear_rect](vk::CommandBuffer cmdbuf) { 367 scheduler.Record([color_attachment, clear_value, clear_rect](vk::CommandBuffer cmdbuf) {
366 const VkClearAttachment attachment{ 368 const VkClearAttachment attachment{
367 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 369 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 7524e3c40..bfae73b60 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -411,8 +411,9 @@ void GRenderWindow::mousePressEvent(QMouseEvent* event) {
411 if (event->source() == Qt::MouseEventSynthesizedBySystem) { 411 if (event->source() == Qt::MouseEventSynthesizedBySystem) {
412 return; 412 return;
413 } 413 }
414 414 // Qt sometimes returns the parent coordinates. To avoid this we read the global mouse
415 auto pos = event->pos(); 415 // coordinates and map them to the current render area
416 const auto pos = mapFromGlobal(QCursor::pos());
416 const auto [x, y] = ScaleTouch(pos); 417 const auto [x, y] = ScaleTouch(pos);
417 const auto button = QtButtonToMouseButton(event->button()); 418 const auto button = QtButtonToMouseButton(event->button());
418 input_subsystem->GetMouse()->PressButton(x, y, button); 419 input_subsystem->GetMouse()->PressButton(x, y, button);
@@ -429,7 +430,9 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
429 if (event->source() == Qt::MouseEventSynthesizedBySystem) { 430 if (event->source() == Qt::MouseEventSynthesizedBySystem) {
430 return; 431 return;
431 } 432 }
432 auto pos = event->pos(); 433 // Qt sometimes returns the parent coordinates. To avoid this we read the global mouse
434 // coordinates and map them to the current render area
435 const auto pos = mapFromGlobal(QCursor::pos());
433 const auto [x, y] = ScaleTouch(pos); 436 const auto [x, y] = ScaleTouch(pos);
434 const int center_x = width() / 2; 437 const int center_x = width() / 2;
435 const int center_y = height() / 2; 438 const int center_y = height() / 2;
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 8c71ad5c1..a5e032959 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -311,16 +311,6 @@ void Config::WriteBasicSetting(const Settings::BasicSetting<std::string>& settin
311 qt_config->setValue(name, QString::fromStdString(value)); 311 qt_config->setValue(name, QString::fromStdString(value));
312} 312}
313 313
314// Explicit float definition: use a double as Qt doesn't write legible floats to config files
315template <>
316void Config::WriteBasicSetting(const Settings::BasicSetting<float>& setting) {
317 const QString name = QString::fromStdString(setting.GetLabel());
318 const double value = setting.GetValue();
319 qt_config->setValue(name + QStringLiteral("/default"),
320 setting.GetValue() == setting.GetDefault());
321 qt_config->setValue(name, value);
322}
323
324template <typename Type> 314template <typename Type>
325void Config::WriteBasicSetting(const Settings::BasicSetting<Type>& setting) { 315void Config::WriteBasicSetting(const Settings::BasicSetting<Type>& setting) {
326 const QString name = QString::fromStdString(setting.GetLabel()); 316 const QString name = QString::fromStdString(setting.GetLabel());
@@ -329,21 +319,6 @@ void Config::WriteBasicSetting(const Settings::BasicSetting<Type>& setting) {
329 qt_config->setValue(name, value); 319 qt_config->setValue(name, value);
330} 320}
331 321
332// Explicit float definition: use a double as Qt doesn't write legible floats to config files
333template <>
334void Config::WriteGlobalSetting(const Settings::Setting<float>& setting) {
335 const QString name = QString::fromStdString(setting.GetLabel());
336 const double value = setting.GetValue(global);
337 if (!global) {
338 qt_config->setValue(name + QStringLiteral("/use_global"), setting.UsingGlobal());
339 }
340 if (global || !setting.UsingGlobal()) {
341 qt_config->setValue(name + QStringLiteral("/default"),
342 setting.GetValue(global) == setting.GetDefault());
343 qt_config->setValue(name, value);
344 }
345}
346
347template <typename Type> 322template <typename Type>
348void Config::WriteGlobalSetting(const Settings::Setting<Type>& setting) { 323void Config::WriteGlobalSetting(const Settings::Setting<Type>& setting) {
349 const QString name = QString::fromStdString(setting.GetLabel()); 324 const QString name = QString::fromStdString(setting.GetLabel());
diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp
index 5aba1a3b2..1d84bf4ed 100644
--- a/src/yuzu/configuration/configure_audio.cpp
+++ b/src/yuzu/configuration/configure_audio.cpp
@@ -47,7 +47,8 @@ void ConfigureAudio::SetConfiguration() {
47 47
48 SetAudioDeviceFromDeviceID(); 48 SetAudioDeviceFromDeviceID();
49 49
50 ui->volume_slider->setValue(Settings::values.volume.GetValue() * ui->volume_slider->maximum()); 50 const auto volume_value = static_cast<int>(Settings::values.volume.GetValue());
51 ui->volume_slider->setValue(volume_value);
51 52
52 ui->toggle_audio_stretching->setChecked(Settings::values.enable_audio_stretching.GetValue()); 53 ui->toggle_audio_stretching->setChecked(Settings::values.enable_audio_stretching.GetValue());
53 54
@@ -112,18 +113,16 @@ void ConfigureAudio::ApplyConfiguration() {
112 113
113 // Guard if during game and set to game-specific value 114 // Guard if during game and set to game-specific value
114 if (Settings::values.volume.UsingGlobal()) { 115 if (Settings::values.volume.UsingGlobal()) {
115 Settings::values.volume.SetValue( 116 const auto volume = static_cast<u8>(ui->volume_slider->value());
116 static_cast<float>(ui->volume_slider->sliderPosition()) / 117 Settings::values.volume.SetValue(volume);
117 ui->volume_slider->maximum());
118 } 118 }
119 } else { 119 } else {
120 if (ui->volume_combo_box->currentIndex() == 0) { 120 if (ui->volume_combo_box->currentIndex() == 0) {
121 Settings::values.volume.SetGlobal(true); 121 Settings::values.volume.SetGlobal(true);
122 } else { 122 } else {
123 Settings::values.volume.SetGlobal(false); 123 Settings::values.volume.SetGlobal(false);
124 Settings::values.volume.SetValue( 124 const auto volume = static_cast<u8>(ui->volume_slider->value());
125 static_cast<float>(ui->volume_slider->sliderPosition()) / 125 Settings::values.volume.SetValue(volume);
126 ui->volume_slider->maximum());
127 } 126 }
128 } 127 }
129} 128}
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp
index 41a69d9b8..4d5b4c0e6 100644
--- a/src/yuzu/configuration/configure_graphics.cpp
+++ b/src/yuzu/configuration/configure_graphics.cpp
@@ -101,9 +101,9 @@ void ConfigureGraphics::SetConfiguration() {
101 ConfigurationShared::SetHighlight(ui->bg_layout, !Settings::values.bg_red.UsingGlobal()); 101 ConfigurationShared::SetHighlight(ui->bg_layout, !Settings::values.bg_red.UsingGlobal());
102 } 102 }
103 103
104 UpdateBackgroundColorButton(QColor::fromRgbF(Settings::values.bg_red.GetValue(), 104 UpdateBackgroundColorButton(QColor::fromRgb(Settings::values.bg_red.GetValue(),
105 Settings::values.bg_green.GetValue(), 105 Settings::values.bg_green.GetValue(),
106 Settings::values.bg_blue.GetValue())); 106 Settings::values.bg_blue.GetValue()));
107 UpdateDeviceComboBox(); 107 UpdateDeviceComboBox();
108} 108}
109 109
@@ -132,9 +132,9 @@ void ConfigureGraphics::ApplyConfiguration() {
132 Settings::values.vulkan_device.SetValue(vulkan_device); 132 Settings::values.vulkan_device.SetValue(vulkan_device);
133 } 133 }
134 if (Settings::values.bg_red.UsingGlobal()) { 134 if (Settings::values.bg_red.UsingGlobal()) {
135 Settings::values.bg_red.SetValue(static_cast<float>(bg_color.redF())); 135 Settings::values.bg_red.SetValue(static_cast<u8>(bg_color.red()));
136 Settings::values.bg_green.SetValue(static_cast<float>(bg_color.greenF())); 136 Settings::values.bg_green.SetValue(static_cast<u8>(bg_color.green()));
137 Settings::values.bg_blue.SetValue(static_cast<float>(bg_color.blueF())); 137 Settings::values.bg_blue.SetValue(static_cast<u8>(bg_color.blue()));
138 } 138 }
139 } else { 139 } else {
140 if (ui->api->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { 140 if (ui->api->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
@@ -159,9 +159,9 @@ void ConfigureGraphics::ApplyConfiguration() {
159 Settings::values.bg_red.SetGlobal(false); 159 Settings::values.bg_red.SetGlobal(false);
160 Settings::values.bg_green.SetGlobal(false); 160 Settings::values.bg_green.SetGlobal(false);
161 Settings::values.bg_blue.SetGlobal(false); 161 Settings::values.bg_blue.SetGlobal(false);
162 Settings::values.bg_red.SetValue(static_cast<float>(bg_color.redF())); 162 Settings::values.bg_red.SetValue(static_cast<u8>(bg_color.red()));
163 Settings::values.bg_green.SetValue(static_cast<float>(bg_color.greenF())); 163 Settings::values.bg_green.SetValue(static_cast<u8>(bg_color.green()));
164 Settings::values.bg_blue.SetValue(static_cast<float>(bg_color.blueF())); 164 Settings::values.bg_blue.SetValue(static_cast<u8>(bg_color.blue()));
165 } 165 }
166 } 166 }
167} 167}
diff --git a/src/yuzu/configuration/configure_input_advanced.ui b/src/yuzu/configuration/configure_input_advanced.ui
index 173130d8d..d3ef5bd06 100644
--- a/src/yuzu/configuration/configure_input_advanced.ui
+++ b/src/yuzu/configuration/configure_input_advanced.ui
@@ -2573,27 +2573,24 @@
2573 </widget> 2573 </widget>
2574 </item> 2574 </item>
2575 <item row="2" column="2"> 2575 <item row="2" column="2">
2576 <widget class="QDoubleSpinBox" name="mouse_panning_sensitivity"> 2576 <widget class="QSpinBox" name="mouse_panning_sensitivity">
2577 <property name="toolTip"> 2577 <property name="toolTip">
2578 <string>Mouse sensitivity</string> 2578 <string>Mouse sensitivity</string>
2579 </property> 2579 </property>
2580 <property name="alignment"> 2580 <property name="alignment">
2581 <set>Qt::AlignCenter</set> 2581 <set>Qt::AlignCenter</set>
2582 </property> 2582 </property>
2583 <property name="decimals"> 2583 <property name="suffix">
2584 <number>2</number> 2584 <string>%</string>
2585 </property> 2585 </property>
2586 <property name="minimum"> 2586 <property name="minimum">
2587 <double>0.100000000000000</double> 2587 <number>1</number>
2588 </property> 2588 </property>
2589 <property name="maximum"> 2589 <property name="maximum">
2590 <double>16.000000000000000</double> 2590 <number>100</number>
2591 </property>
2592 <property name="singleStep">
2593 <double>0.010000000000000</double>
2594 </property> 2591 </property>
2595 <property name="value"> 2592 <property name="value">
2596 <double>1.000000000000000</double> 2593 <number>100</number>
2597 </property> 2594 </property>
2598 </widget> 2595 </widget>
2599 </item> 2596 </item>
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index 325584a1a..23ada3f92 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -242,17 +242,15 @@ static const std::array<int, 8> keyboard_mods{
242}; 242};
243 243
244template <> 244template <>
245void Config::ReadSetting(const std::string& group, Settings::BasicSetting<float>& setting) {
246 setting = sdl2_config->GetReal(group, setting.GetLabel(), setting.GetDefault());
247}
248template <>
249void Config::ReadSetting(const std::string& group, Settings::BasicSetting<std::string>& setting) { 245void Config::ReadSetting(const std::string& group, Settings::BasicSetting<std::string>& setting) {
250 setting = sdl2_config->Get(group, setting.GetLabel(), setting.GetDefault()); 246 setting = sdl2_config->Get(group, setting.GetLabel(), setting.GetDefault());
251} 247}
248
252template <> 249template <>
253void Config::ReadSetting(const std::string& group, Settings::BasicSetting<bool>& setting) { 250void Config::ReadSetting(const std::string& group, Settings::BasicSetting<bool>& setting) {
254 setting = sdl2_config->GetBoolean(group, setting.GetLabel(), setting.GetDefault()); 251 setting = sdl2_config->GetBoolean(group, setting.GetLabel(), setting.GetDefault());
255} 252}
253
256template <typename Type> 254template <typename Type>
257void Config::ReadSetting(const std::string& group, Settings::BasicSetting<Type>& setting) { 255void Config::ReadSetting(const std::string& group, Settings::BasicSetting<Type>& setting) {
258 setting = static_cast<Type>(sdl2_config->GetInteger(group, setting.GetLabel(), 256 setting = static_cast<Type>(sdl2_config->GetInteger(group, setting.GetLabel(),
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h
index cc9850aad..7d6bcccc7 100644
--- a/src/yuzu_cmd/default_ini.h
+++ b/src/yuzu_cmd/default_ini.h
@@ -232,7 +232,7 @@ use_vsync =
232use_caches_gc = 232use_caches_gc =
233 233
234# The clear color for the renderer. What shows up on the sides of the bottom screen. 234# The clear color for the renderer. What shows up on the sides of the bottom screen.
235# Must be in range of 0.0-1.0. Defaults to 1.0 for all. 235# Must be in range of 0-255. Defaults to 0 for all.
236bg_red = 236bg_red =
237bg_blue = 237bg_blue =
238bg_green = 238bg_green =
@@ -281,7 +281,7 @@ enable_audio_stretching =
281output_device = 281output_device =
282 282
283# Output volume. 283# Output volume.
284# 1.0 (default): 100%, 0.0; mute 284# 100 (default): 100%, 0; mute
285volume = 285volume =
286 286
287[Data Storage] 287[Data Storage]