summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/core.cpp9
-rw-r--r--src/core/hle/kernel/k_server_session.h2
-rw-r--r--src/core/hle/kernel/k_thread.cpp6
-rw-r--r--src/core/hle/service/am/am.cpp13
-rw-r--r--src/core/hle/service/am/am.h1
-rw-r--r--src/core/hle/service/nvdrv/core/nvmap.cpp5
-rw-r--r--src/core/hle/service/nvdrv/core/nvmap.h1
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.cpp10
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue_producer.cpp7
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp13
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.h5
-rw-r--r--src/core/hle/service/sm/sm.cpp8
-rw-r--r--src/core/hle/service/sm/sm_controller.cpp33
-rw-r--r--src/core/hle/service/vi/display/vi_display.h6
-rw-r--r--src/core/hle/service/vi/vi.cpp8
-rw-r--r--src/video_core/engines/maxwell_3d.cpp129
-rw-r--r--src/video_core/engines/maxwell_3d.h2
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp21
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp12
-rw-r--r--src/yuzu/configuration/config.cpp2
-rw-r--r--src/yuzu/configuration/configure_ui.cpp3
-rw-r--r--src/yuzu/configuration/configure_ui.ui7
-rw-r--r--src/yuzu/game_list.cpp2
-rw-r--r--src/yuzu/uisettings.h3
24 files changed, 204 insertions, 104 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 40a610435..d8934be52 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -137,6 +137,7 @@ struct System::Impl {
137 device_memory = std::make_unique<Core::DeviceMemory>(); 137 device_memory = std::make_unique<Core::DeviceMemory>();
138 138
139 is_multicore = Settings::values.use_multi_core.GetValue(); 139 is_multicore = Settings::values.use_multi_core.GetValue();
140 extended_memory_layout = Settings::values.use_extended_memory_layout.GetValue();
140 141
141 core_timing.SetMulticore(is_multicore); 142 core_timing.SetMulticore(is_multicore);
142 core_timing.Initialize([&system]() { system.RegisterHostThread(); }); 143 core_timing.Initialize([&system]() { system.RegisterHostThread(); });
@@ -166,13 +167,18 @@ struct System::Impl {
166 } 167 }
167 168
168 void ReinitializeIfNecessary(System& system) { 169 void ReinitializeIfNecessary(System& system) {
169 if (is_multicore == Settings::values.use_multi_core.GetValue()) { 170 const bool must_reinitialize =
171 is_multicore != Settings::values.use_multi_core.GetValue() ||
172 extended_memory_layout != Settings::values.use_extended_memory_layout.GetValue();
173
174 if (!must_reinitialize) {
170 return; 175 return;
171 } 176 }
172 177
173 LOG_DEBUG(Kernel, "Re-initializing"); 178 LOG_DEBUG(Kernel, "Re-initializing");
174 179
175 is_multicore = Settings::values.use_multi_core.GetValue(); 180 is_multicore = Settings::values.use_multi_core.GetValue();
181 extended_memory_layout = Settings::values.use_extended_memory_layout.GetValue();
176 182
177 Initialize(system); 183 Initialize(system);
178 } 184 }
@@ -521,6 +527,7 @@ struct System::Impl {
521 527
522 bool is_multicore{}; 528 bool is_multicore{};
523 bool is_async_gpu{}; 529 bool is_async_gpu{};
530 bool extended_memory_layout{};
524 531
525 ExecuteProgramCallback execute_program_callback; 532 ExecuteProgramCallback execute_program_callback;
526 ExitCallback exit_callback; 533 ExitCallback exit_callback;
diff --git a/src/core/hle/kernel/k_server_session.h b/src/core/hle/kernel/k_server_session.h
index 32135473b..188aef4af 100644
--- a/src/core/hle/kernel/k_server_session.h
+++ b/src/core/hle/kernel/k_server_session.h
@@ -91,7 +91,7 @@ private:
91 91
92 /// List of threads which are pending a reply. 92 /// List of threads which are pending a reply.
93 boost::intrusive::list<KSessionRequest> m_request_list; 93 boost::intrusive::list<KSessionRequest> m_request_list;
94 KSessionRequest* m_current_request; 94 KSessionRequest* m_current_request{};
95 95
96 KLightLock m_lock; 96 KLightLock m_lock;
97}; 97};
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index d57b42fdf..cc88d08f0 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -1185,8 +1185,10 @@ void KThread::RequestDummyThreadWait() {
1185} 1185}
1186 1186
1187void KThread::DummyThreadBeginWait() { 1187void KThread::DummyThreadBeginWait() {
1188 ASSERT(this->IsDummyThread()); 1188 if (!this->IsDummyThread() || kernel.IsPhantomModeForSingleCore()) {
1189 ASSERT(!kernel.IsPhantomModeForSingleCore()); 1189 // Occurs in single core mode.
1190 return;
1191 }
1190 1192
1191 // Block until runnable is no longer false. 1193 // Block until runnable is no longer false.
1192 dummy_thread_runnable.wait(false); 1194 dummy_thread_runnable.wait(false);
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index e55233054..8ea7fd760 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -299,7 +299,7 @@ ISelfController::ISelfController(Core::System& system_, NVFlinger::NVFlinger& nv
299 {100, &ISelfController::SetAlbumImageTakenNotificationEnabled, "SetAlbumImageTakenNotificationEnabled"}, 299 {100, &ISelfController::SetAlbumImageTakenNotificationEnabled, "SetAlbumImageTakenNotificationEnabled"},
300 {110, nullptr, "SetApplicationAlbumUserData"}, 300 {110, nullptr, "SetApplicationAlbumUserData"},
301 {120, &ISelfController::SaveCurrentScreenshot, "SaveCurrentScreenshot"}, 301 {120, &ISelfController::SaveCurrentScreenshot, "SaveCurrentScreenshot"},
302 {130, nullptr, "SetRecordVolumeMuted"}, 302 {130, &ISelfController::SetRecordVolumeMuted, "SetRecordVolumeMuted"},
303 {1000, nullptr, "GetDebugStorageChannel"}, 303 {1000, nullptr, "GetDebugStorageChannel"},
304 }; 304 };
305 // clang-format on 305 // clang-format on
@@ -597,6 +597,17 @@ void ISelfController::SaveCurrentScreenshot(Kernel::HLERequestContext& ctx) {
597 rb.Push(ResultSuccess); 597 rb.Push(ResultSuccess);
598} 598}
599 599
600void ISelfController::SetRecordVolumeMuted(Kernel::HLERequestContext& ctx) {
601 IPC::RequestParser rp{ctx};
602
603 const auto is_record_volume_muted = rp.Pop<bool>();
604
605 LOG_WARNING(Service_AM, "(STUBBED) called. is_record_volume_muted={}", is_record_volume_muted);
606
607 IPC::ResponseBuilder rb{ctx, 2};
608 rb.Push(ResultSuccess);
609}
610
600AppletMessageQueue::AppletMessageQueue(Core::System& system) 611AppletMessageQueue::AppletMessageQueue(Core::System& system)
601 : service_context{system, "AppletMessageQueue"} { 612 : service_context{system, "AppletMessageQueue"} {
602 on_new_message = service_context.CreateEvent("AMMessageQueue:OnMessageReceived"); 613 on_new_message = service_context.CreateEvent("AMMessageQueue:OnMessageReceived");
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index bb75c6281..a0fbfcfc5 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -182,6 +182,7 @@ private:
182 void GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequestContext& ctx); 182 void GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequestContext& ctx);
183 void SetAlbumImageTakenNotificationEnabled(Kernel::HLERequestContext& ctx); 183 void SetAlbumImageTakenNotificationEnabled(Kernel::HLERequestContext& ctx);
184 void SaveCurrentScreenshot(Kernel::HLERequestContext& ctx); 184 void SaveCurrentScreenshot(Kernel::HLERequestContext& ctx);
185 void SetRecordVolumeMuted(Kernel::HLERequestContext& ctx);
185 186
186 enum class ScreenshotPermission : u32 { 187 enum class ScreenshotPermission : u32 {
187 Inherit = 0, 188 Inherit = 0,
diff --git a/src/core/hle/service/nvdrv/core/nvmap.cpp b/src/core/hle/service/nvdrv/core/nvmap.cpp
index fbd8a74a5..a51ca5444 100644
--- a/src/core/hle/service/nvdrv/core/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/core/nvmap.cpp
@@ -255,15 +255,16 @@ std::optional<NvMap::FreeInfo> NvMap::FreeHandle(Handle::Id handle, bool interna
255 .address = handle_description->address, 255 .address = handle_description->address,
256 .size = handle_description->size, 256 .size = handle_description->size,
257 .was_uncached = handle_description->flags.map_uncached.Value() != 0, 257 .was_uncached = handle_description->flags.map_uncached.Value() != 0,
258 .can_unlock = true,
258 }; 259 };
259 } else { 260 } else {
260 return std::nullopt; 261 return std::nullopt;
261 } 262 }
262 263
263 // Handle hasn't been freed from memory, set address to 0 to mark that the handle wasn't freed 264 // If the handle hasn't been freed from memory, mark that
264 if (!hWeak.expired()) { 265 if (!hWeak.expired()) {
265 LOG_DEBUG(Service_NVDRV, "nvmap handle: {} wasn't freed as it is still in use", handle); 266 LOG_DEBUG(Service_NVDRV, "nvmap handle: {} wasn't freed as it is still in use", handle);
266 freeInfo.address = 0; 267 freeInfo.can_unlock = false;
267 } 268 }
268 269
269 return freeInfo; 270 return freeInfo;
diff --git a/src/core/hle/service/nvdrv/core/nvmap.h b/src/core/hle/service/nvdrv/core/nvmap.h
index b9dd3801f..a8e573890 100644
--- a/src/core/hle/service/nvdrv/core/nvmap.h
+++ b/src/core/hle/service/nvdrv/core/nvmap.h
@@ -105,6 +105,7 @@ public:
105 u64 address; //!< Address the handle referred to before deletion 105 u64 address; //!< Address the handle referred to before deletion
106 u64 size; //!< Page-aligned handle size 106 u64 size; //!< Page-aligned handle size
107 bool was_uncached; //!< If the handle was allocated as uncached 107 bool was_uncached; //!< If the handle was allocated as uncached
108 bool can_unlock; //!< If the address region is ready to be unlocked
108 }; 109 };
109 110
110 explicit NvMap(Tegra::Host1x::Host1x& host1x); 111 explicit NvMap(Tegra::Host1x::Host1x& host1x);
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp
index b60679021..44388655d 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp
@@ -251,10 +251,12 @@ NvResult nvmap::IocFree(const std::vector<u8>& input, std::vector<u8>& output) {
251 } 251 }
252 252
253 if (auto freeInfo{file.FreeHandle(params.handle, false)}) { 253 if (auto freeInfo{file.FreeHandle(params.handle, false)}) {
254 ASSERT(system.CurrentProcess() 254 if (freeInfo->can_unlock) {
255 ->PageTable() 255 ASSERT(system.CurrentProcess()
256 .UnlockForDeviceAddressSpace(freeInfo->address, freeInfo->size) 256 ->PageTable()
257 .IsSuccess()); 257 .UnlockForDeviceAddressSpace(freeInfo->address, freeInfo->size)
258 .IsSuccess());
259 }
258 params.address = freeInfo->address; 260 params.address = freeInfo->address;
259 params.size = static_cast<u32>(freeInfo->size); 261 params.size = static_cast<u32>(freeInfo->size);
260 params.flags.raw = 0; 262 params.flags.raw = 0;
diff --git a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp
index 77ddbb6ef..41ba44b21 100644
--- a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp
@@ -742,6 +742,13 @@ Status BufferQueueProducer::Disconnect(NativeWindowApi api) {
742 return Status::NoError; 742 return Status::NoError;
743 } 743 }
744 744
745 // HACK: We are not Android. Remove handle for items in queue, and clear queue.
746 // Allows synchronous destruction of nvmap handles.
747 for (auto& item : core->queue) {
748 nvmap.FreeHandle(item.graphic_buffer->BufferId(), true);
749 }
750 core->queue.clear();
751
745 switch (api) { 752 switch (api) {
746 case NativeWindowApi::Egl: 753 case NativeWindowApi::Egl:
747 case NativeWindowApi::Cpu: 754 case NativeWindowApi::Cpu:
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index dad93b38e..c3af12c90 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -138,6 +138,19 @@ std::optional<u64> NVFlinger::OpenDisplay(std::string_view name) {
138 return itr->GetID(); 138 return itr->GetID();
139} 139}
140 140
141bool NVFlinger::CloseDisplay(u64 display_id) {
142 const auto lock_guard = Lock();
143 auto* const display = FindDisplay(display_id);
144
145 if (display == nullptr) {
146 return false;
147 }
148
149 display->Reset();
150
151 return true;
152}
153
141std::optional<u64> NVFlinger::CreateLayer(u64 display_id) { 154std::optional<u64> NVFlinger::CreateLayer(u64 display_id) {
142 const auto lock_guard = Lock(); 155 const auto lock_guard = Lock();
143 auto* const display = FindDisplay(display_id); 156 auto* const display = FindDisplay(display_id);
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h
index b8191c595..460bef976 100644
--- a/src/core/hle/service/nvflinger/nvflinger.h
+++ b/src/core/hle/service/nvflinger/nvflinger.h
@@ -58,6 +58,11 @@ public:
58 /// If an invalid display name is provided, then an empty optional is returned. 58 /// If an invalid display name is provided, then an empty optional is returned.
59 [[nodiscard]] std::optional<u64> OpenDisplay(std::string_view name); 59 [[nodiscard]] std::optional<u64> OpenDisplay(std::string_view name);
60 60
61 /// Closes the specified display by its ID.
62 ///
63 /// Returns false if an invalid display ID is provided.
64 [[nodiscard]] bool CloseDisplay(u64 display_id);
65
61 /// Creates a layer on the specified display and returns the layer ID. 66 /// Creates a layer on the specified display and returns the layer ID.
62 /// 67 ///
63 /// If an invalid display ID is specified, then an empty optional is returned. 68 /// If an invalid display ID is specified, then an empty optional is returned.
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp
index 48e70f93c..cb6c0e96f 100644
--- a/src/core/hle/service/sm/sm.cpp
+++ b/src/core/hle/service/sm/sm.cpp
@@ -80,7 +80,6 @@ ResultVal<Kernel::KPort*> ServiceManager::GetServicePort(const std::string& name
80 } 80 }
81 81
82 auto* port = Kernel::KPort::Create(kernel); 82 auto* port = Kernel::KPort::Create(kernel);
83 SCOPE_EXIT({ port->Close(); });
84 83
85 port->Initialize(ServerSessionCountMax, false, name); 84 port->Initialize(ServerSessionCountMax, false, name);
86 auto handler = it->second; 85 auto handler = it->second;
@@ -150,9 +149,10 @@ ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext&
150 return port_result.Code(); 149 return port_result.Code();
151 } 150 }
152 auto& port = port_result.Unwrap(); 151 auto& port = port_result.Unwrap();
153 SCOPE_EXIT({ port->GetClientPort().Close(); }); 152 SCOPE_EXIT({
154 153 port->GetClientPort().Close();
155 kernel.RegisterServerObject(&port->GetServerPort()); 154 port->GetServerPort().Close();
155 });
156 156
157 // Create a new session. 157 // Create a new session.
158 Kernel::KClientSession* session{}; 158 Kernel::KClientSession* session{};
diff --git a/src/core/hle/service/sm/sm_controller.cpp b/src/core/hle/service/sm/sm_controller.cpp
index 273f79568..46a8439d8 100644
--- a/src/core/hle/service/sm/sm_controller.cpp
+++ b/src/core/hle/service/sm/sm_controller.cpp
@@ -28,23 +28,36 @@ void Controller::ConvertCurrentObjectToDomain(Kernel::HLERequestContext& ctx) {
28void Controller::CloneCurrentObject(Kernel::HLERequestContext& ctx) { 28void Controller::CloneCurrentObject(Kernel::HLERequestContext& ctx) {
29 LOG_DEBUG(Service, "called"); 29 LOG_DEBUG(Service, "called");
30 30
31 auto& process = *ctx.GetThread().GetOwnerProcess();
31 auto& parent_session = *ctx.Session()->GetParent(); 32 auto& parent_session = *ctx.Session()->GetParent();
32 auto& parent_port = parent_session.GetParent()->GetParent()->GetClientPort();
33 auto& session_manager = parent_session.GetServerSession().GetSessionRequestManager(); 33 auto& session_manager = parent_session.GetServerSession().GetSessionRequestManager();
34 auto& session_handler = session_manager->SessionHandler();
34 35
35 // Create a session. 36 // FIXME: this is duplicated from the SVC, it should just call it instead
36 Kernel::KClientSession* session{}; 37 // once this is a proper process
37 const Result result = parent_port.CreateSession(std::addressof(session), session_manager); 38
38 if (result.IsError()) { 39 // Reserve a new session from the process resource limit.
39 LOG_CRITICAL(Service, "CreateSession failed with error 0x{:08X}", result.raw); 40 Kernel::KScopedResourceReservation session_reservation(&process,
40 IPC::ResponseBuilder rb{ctx, 2}; 41 Kernel::LimitableResource::Sessions);
41 rb.Push(result); 42 ASSERT(session_reservation.Succeeded());
42 } 43
44 // Create the session.
45 Kernel::KSession* session = Kernel::KSession::Create(system.Kernel());
46 ASSERT(session != nullptr);
47
48 // Initialize the session.
49 session->Initialize(nullptr, parent_session.GetName(), session_manager);
50
51 // Commit the session reservation.
52 session_reservation.Commit();
53
54 // Register the session.
55 session_handler.ClientConnected(&session->GetServerSession());
43 56
44 // We succeeded. 57 // We succeeded.
45 IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; 58 IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
46 rb.Push(ResultSuccess); 59 rb.Push(ResultSuccess);
47 rb.PushMoveObjects(session); 60 rb.PushMoveObjects(session->GetClientSession());
48} 61}
49 62
50void Controller::CloneCurrentObjectEx(Kernel::HLERequestContext& ctx) { 63void Controller::CloneCurrentObjectEx(Kernel::HLERequestContext& ctx) {
diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h
index 33d5f398c..0b65a65da 100644
--- a/src/core/hle/service/vi/display/vi_display.h
+++ b/src/core/hle/service/vi/display/vi_display.h
@@ -106,6 +106,12 @@ public:
106 /// 106 ///
107 void CloseLayer(u64 layer_id); 107 void CloseLayer(u64 layer_id);
108 108
109 /// Resets the display for a new connection.
110 void Reset() {
111 layers.clear();
112 got_vsync_event = false;
113 }
114
109 /// Attempts to find a layer with the given ID. 115 /// Attempts to find a layer with the given ID.
110 /// 116 ///
111 /// @param layer_id The layer ID. 117 /// @param layer_id The layer ID.
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 9c917cacf..bb283e74e 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -324,10 +324,10 @@ private:
324 IPC::RequestParser rp{ctx}; 324 IPC::RequestParser rp{ctx};
325 const u64 display = rp.Pop<u64>(); 325 const u64 display = rp.Pop<u64>();
326 326
327 LOG_WARNING(Service_VI, "(STUBBED) called. display=0x{:016X}", display); 327 const Result rc = nv_flinger.CloseDisplay(display) ? ResultSuccess : ResultUnknown;
328 328
329 IPC::ResponseBuilder rb{ctx, 2}; 329 IPC::ResponseBuilder rb{ctx, 2};
330 rb.Push(ResultSuccess); 330 rb.Push(rc);
331 } 331 }
332 332
333 void CreateManagedLayer(Kernel::HLERequestContext& ctx) { 333 void CreateManagedLayer(Kernel::HLERequestContext& ctx) {
@@ -508,10 +508,10 @@ private:
508 IPC::RequestParser rp{ctx}; 508 IPC::RequestParser rp{ctx};
509 const u64 display_id = rp.Pop<u64>(); 509 const u64 display_id = rp.Pop<u64>();
510 510
511 LOG_WARNING(Service_VI, "(STUBBED) called. display_id=0x{:016X}", display_id); 511 const Result rc = nv_flinger.CloseDisplay(display_id) ? ResultSuccess : ResultUnknown;
512 512
513 IPC::ResponseBuilder rb{ctx, 2}; 513 IPC::ResponseBuilder rb{ctx, 2};
514 rb.Push(ResultSuccess); 514 rb.Push(rc);
515 } 515 }
516 516
517 // This literally does nothing internally in the actual service itself, 517 // This literally does nothing internally in the actual service itself,
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index 5208bea75..f9794dfe4 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -123,9 +123,6 @@ void Maxwell3D::InitializeRegisterDefaults() {
123 draw_command[MAXWELL3D_REG_INDEX(vertex_buffer.count)] = true; 123 draw_command[MAXWELL3D_REG_INDEX(vertex_buffer.count)] = true;
124 draw_command[MAXWELL3D_REG_INDEX(index_buffer.first)] = true; 124 draw_command[MAXWELL3D_REG_INDEX(index_buffer.first)] = true;
125 draw_command[MAXWELL3D_REG_INDEX(index_buffer.count)] = true; 125 draw_command[MAXWELL3D_REG_INDEX(index_buffer.count)] = true;
126 draw_command[MAXWELL3D_REG_INDEX(index_buffer32_first)] = true;
127 draw_command[MAXWELL3D_REG_INDEX(index_buffer16_first)] = true;
128 draw_command[MAXWELL3D_REG_INDEX(index_buffer8_first)] = true;
129 draw_command[MAXWELL3D_REG_INDEX(draw_inline_index)] = true; 126 draw_command[MAXWELL3D_REG_INDEX(draw_inline_index)] = true;
130 draw_command[MAXWELL3D_REG_INDEX(inline_index_2x16.even)] = true; 127 draw_command[MAXWELL3D_REG_INDEX(inline_index_2x16.even)] = true;
131 draw_command[MAXWELL3D_REG_INDEX(inline_index_4x8.index0)] = true; 128 draw_command[MAXWELL3D_REG_INDEX(inline_index_4x8.index0)] = true;
@@ -216,6 +213,21 @@ void Maxwell3D::ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argume
216 return ProcessCBBind(3); 213 return ProcessCBBind(3);
217 case MAXWELL3D_REG_INDEX(bind_groups[4].raw_config): 214 case MAXWELL3D_REG_INDEX(bind_groups[4].raw_config):
218 return ProcessCBBind(4); 215 return ProcessCBBind(4);
216 case MAXWELL3D_REG_INDEX(index_buffer32_first):
217 regs.index_buffer.count = regs.index_buffer32_first.count;
218 regs.index_buffer.first = regs.index_buffer32_first.first;
219 dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
220 return ProcessDraw();
221 case MAXWELL3D_REG_INDEX(index_buffer16_first):
222 regs.index_buffer.count = regs.index_buffer16_first.count;
223 regs.index_buffer.first = regs.index_buffer16_first.first;
224 dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
225 return ProcessDraw();
226 case MAXWELL3D_REG_INDEX(index_buffer8_first):
227 regs.index_buffer.count = regs.index_buffer8_first.count;
228 regs.index_buffer.first = regs.index_buffer8_first.first;
229 dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
230 return ProcessDraw();
219 case MAXWELL3D_REG_INDEX(topology_override): 231 case MAXWELL3D_REG_INDEX(topology_override):
220 use_topology_override = true; 232 use_topology_override = true;
221 return; 233 return;
@@ -583,6 +595,31 @@ void Maxwell3D::ProcessClearBuffers() {
583 rasterizer->Clear(); 595 rasterizer->Clear();
584} 596}
585 597
598void Maxwell3D::ProcessDraw(u32 instance_count) {
599 LOG_TRACE(HW_GPU, "called, topology={}, count={}", regs.draw.topology.Value(),
600 regs.vertex_buffer.count);
601
602 ASSERT_MSG(!(regs.index_buffer.count && regs.vertex_buffer.count), "Both indexed and direct?");
603
604 // Both instance configuration registers can not be set at the same time.
605 ASSERT_MSG(regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::First ||
606 regs.draw.instance_id != Maxwell3D::Regs::Draw::InstanceId::Unchanged,
607 "Illegal combination of instancing parameters");
608
609 ProcessTopologyOverride();
610
611 const bool is_indexed = regs.index_buffer.count && !regs.vertex_buffer.count;
612 if (ShouldExecute()) {
613 rasterizer->Draw(is_indexed, instance_count);
614 }
615
616 if (is_indexed) {
617 regs.index_buffer.count = 0;
618 } else {
619 regs.vertex_buffer.count = 0;
620 }
621}
622
586void Maxwell3D::ProcessDeferredDraw() { 623void Maxwell3D::ProcessDeferredDraw() {
587 if (deferred_draw_method.empty()) { 624 if (deferred_draw_method.empty()) {
588 return; 625 return;
@@ -596,23 +633,28 @@ void Maxwell3D::ProcessDeferredDraw() {
596 DrawMode draw_mode{DrawMode::Undefined}; 633 DrawMode draw_mode{DrawMode::Undefined};
597 u32 instance_count = 1; 634 u32 instance_count = 1;
598 635
599 auto first_method = deferred_draw_method[0]; 636 u32 index = 0;
600 if (MAXWELL3D_REG_INDEX(draw.begin) == first_method) { 637 u32 method = 0;
601 // The minimum number of methods for drawing must be greater than or equal to 638 u32 method_count = static_cast<u32>(deferred_draw_method.size());
602 // 3[draw.begin->vertex(index)count->draw.end] to avoid errors in index mode drawing 639 for (; index < method_count &&
603 if (deferred_draw_method.size() < 3) { 640 (method = deferred_draw_method[index]) != MAXWELL3D_REG_INDEX(draw.begin);
604 return; 641 ++index)
605 } 642 ;
606 draw_mode = (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) || 643
607 (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged) 644 if (MAXWELL3D_REG_INDEX(draw.begin) != method) {
608 ? DrawMode::Instance 645 return;
609 : DrawMode::General;
610 } else if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method ||
611 MAXWELL3D_REG_INDEX(index_buffer16_first) == first_method ||
612 MAXWELL3D_REG_INDEX(index_buffer8_first) == first_method) {
613 draw_mode = DrawMode::General;
614 } 646 }
615 647
648 // The minimum number of methods for drawing must be greater than or equal to
649 // 3[draw.begin->vertex(index)count(first)->draw.end] to avoid errors in index mode drawing
650 if ((method_count - index) < 3) {
651 return;
652 }
653 draw_mode = (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) ||
654 (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged)
655 ? DrawMode::Instance
656 : DrawMode::General;
657
616 // Drawing will only begin with draw.begin or index_buffer method, other methods directly 658 // Drawing will only begin with draw.begin or index_buffer method, other methods directly
617 // clear 659 // clear
618 if (draw_mode == DrawMode::Undefined) { 660 if (draw_mode == DrawMode::Undefined) {
@@ -622,53 +664,18 @@ void Maxwell3D::ProcessDeferredDraw() {
622 664
623 if (draw_mode == DrawMode::Instance) { 665 if (draw_mode == DrawMode::Instance) {
624 ASSERT_MSG(deferred_draw_method.size() % 4 == 0, "Instance mode method size error"); 666 ASSERT_MSG(deferred_draw_method.size() % 4 == 0, "Instance mode method size error");
625 instance_count = static_cast<u32>(deferred_draw_method.size()) / 4; 667 instance_count = static_cast<u32>(method_count - index) / 4;
626 } else { 668 } else {
627 if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method) { 669 method = deferred_draw_method[index + 1];
628 regs.index_buffer.count = regs.index_buffer32_first.count; 670 if (MAXWELL3D_REG_INDEX(draw_inline_index) == method ||
629 regs.index_buffer.first = regs.index_buffer32_first.first; 671 MAXWELL3D_REG_INDEX(inline_index_2x16.even) == method ||
630 dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; 672 MAXWELL3D_REG_INDEX(inline_index_4x8.index0) == method) {
631 } else if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method) { 673 regs.index_buffer.count = static_cast<u32>(inline_index_draw_indexes.size() / 4);
632 regs.index_buffer.count = regs.index_buffer16_first.count; 674 regs.index_buffer.format = Regs::IndexFormat::UnsignedInt;
633 regs.index_buffer.first = regs.index_buffer16_first.first;
634 dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
635 } else if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method) {
636 regs.index_buffer.count = regs.index_buffer8_first.count;
637 regs.index_buffer.first = regs.index_buffer8_first.first;
638 dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
639 } else {
640 auto second_method = deferred_draw_method[1];
641 if (MAXWELL3D_REG_INDEX(draw_inline_index) == second_method ||
642 MAXWELL3D_REG_INDEX(inline_index_2x16.even) == second_method ||
643 MAXWELL3D_REG_INDEX(inline_index_4x8.index0) == second_method) {
644 regs.index_buffer.count = static_cast<u32>(inline_index_draw_indexes.size() / 4);
645 regs.index_buffer.format = Regs::IndexFormat::UnsignedInt;
646 }
647 } 675 }
648 } 676 }
649 677
650 LOG_TRACE(HW_GPU, "called, topology={}, count={}", regs.draw.topology.Value(), 678 ProcessDraw(instance_count);
651 regs.vertex_buffer.count);
652
653 ASSERT_MSG(!(regs.index_buffer.count && regs.vertex_buffer.count), "Both indexed and direct?");
654
655 // Both instance configuration registers can not be set at the same time.
656 ASSERT_MSG(regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::First ||
657 regs.draw.instance_id != Maxwell3D::Regs::Draw::InstanceId::Unchanged,
658 "Illegal combination of instancing parameters");
659
660 ProcessTopologyOverride();
661
662 const bool is_indexed = regs.index_buffer.count && !regs.vertex_buffer.count;
663 if (ShouldExecute()) {
664 rasterizer->Draw(is_indexed, instance_count);
665 }
666
667 if (is_indexed) {
668 regs.index_buffer.count = 0;
669 } else {
670 regs.vertex_buffer.count = 0;
671 }
672 679
673 deferred_draw_method.clear(); 680 deferred_draw_method.clear();
674 inline_index_draw_indexes.clear(); 681 inline_index_draw_indexes.clear();
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index bd23ebc12..a948fcb14 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -3143,6 +3143,8 @@ private:
3143 /// Handles use of topology overrides (e.g., to avoid using a topology assigned from a macro) 3143 /// Handles use of topology overrides (e.g., to avoid using a topology assigned from a macro)
3144 void ProcessTopologyOverride(); 3144 void ProcessTopologyOverride();
3145 3145
3146 void ProcessDraw(u32 instance_count = 1);
3147
3146 void ProcessDeferredDraw(); 3148 void ProcessDeferredDraw();
3147 3149
3148 /// Returns a query's value or an empty object if the value will be deferred through a cache. 3150 /// Returns a query's value or an empty object if the value will be deferred through a cache.
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 9f05a7a18..6ab68892c 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -305,14 +305,19 @@ void RasterizerVulkan::Clear() {
305 } 305 }
306 } 306 }
307 307
308 scheduler.Record([color_attachment, clear_value, clear_rect](vk::CommandBuffer cmdbuf) { 308 if (regs.clear_surface.R && regs.clear_surface.G && regs.clear_surface.B &&
309 const VkClearAttachment attachment{ 309 regs.clear_surface.A) {
310 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 310 scheduler.Record([color_attachment, clear_value, clear_rect](vk::CommandBuffer cmdbuf) {
311 .colorAttachment = color_attachment, 311 const VkClearAttachment attachment{
312 .clearValue = clear_value, 312 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
313 }; 313 .colorAttachment = color_attachment,
314 cmdbuf.ClearAttachments(attachment, clear_rect); 314 .clearValue = clear_value,
315 }); 315 };
316 cmdbuf.ClearAttachments(attachment, clear_rect);
317 });
318 } else {
319 UNIMPLEMENTED_MSG("Unimplemented Clear only the specified channel");
320 }
316 } 321 }
317 322
318 if (!use_depth && !use_stencil) { 323 if (!use_depth && !use_stencil) {
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 305ad8aee..6ad7efbdf 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -1782,17 +1782,17 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
1782 1782
1783 const auto& resolution = runtime.resolution; 1783 const auto& resolution = runtime.resolution;
1784 1784
1785 u32 width = 0; 1785 u32 width = std::numeric_limits<u32>::max();
1786 u32 height = 0; 1786 u32 height = std::numeric_limits<u32>::max();
1787 for (size_t index = 0; index < NUM_RT; ++index) { 1787 for (size_t index = 0; index < NUM_RT; ++index) {
1788 const ImageView* const color_buffer = color_buffers[index]; 1788 const ImageView* const color_buffer = color_buffers[index];
1789 if (!color_buffer) { 1789 if (!color_buffer) {
1790 renderpass_key.color_formats[index] = PixelFormat::Invalid; 1790 renderpass_key.color_formats[index] = PixelFormat::Invalid;
1791 continue; 1791 continue;
1792 } 1792 }
1793 width = std::max(width, is_rescaled ? resolution.ScaleUp(color_buffer->size.width) 1793 width = std::min(width, is_rescaled ? resolution.ScaleUp(color_buffer->size.width)
1794 : color_buffer->size.width); 1794 : color_buffer->size.width);
1795 height = std::max(height, is_rescaled ? resolution.ScaleUp(color_buffer->size.height) 1795 height = std::min(height, is_rescaled ? resolution.ScaleUp(color_buffer->size.height)
1796 : color_buffer->size.height); 1796 : color_buffer->size.height);
1797 attachments.push_back(color_buffer->RenderTarget()); 1797 attachments.push_back(color_buffer->RenderTarget());
1798 renderpass_key.color_formats[index] = color_buffer->format; 1798 renderpass_key.color_formats[index] = color_buffer->format;
@@ -1804,9 +1804,9 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
1804 } 1804 }
1805 const size_t num_colors = attachments.size(); 1805 const size_t num_colors = attachments.size();
1806 if (depth_buffer) { 1806 if (depth_buffer) {
1807 width = std::max(width, is_rescaled ? resolution.ScaleUp(depth_buffer->size.width) 1807 width = std::min(width, is_rescaled ? resolution.ScaleUp(depth_buffer->size.width)
1808 : depth_buffer->size.width); 1808 : depth_buffer->size.width);
1809 height = std::max(height, is_rescaled ? resolution.ScaleUp(depth_buffer->size.height) 1809 height = std::min(height, is_rescaled ? resolution.ScaleUp(depth_buffer->size.height)
1810 : depth_buffer->size.height); 1810 : depth_buffer->size.height);
1811 attachments.push_back(depth_buffer->RenderTarget()); 1811 attachments.push_back(depth_buffer->RenderTarget());
1812 renderpass_key.depth_format = depth_buffer->format; 1812 renderpass_key.depth_format = depth_buffer->format;
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 195074bf2..927dd1069 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -819,6 +819,7 @@ void Config::ReadUIGamelistValues() {
819 qt_config->beginGroup(QStringLiteral("UIGameList")); 819 qt_config->beginGroup(QStringLiteral("UIGameList"));
820 820
821 ReadBasicSetting(UISettings::values.show_add_ons); 821 ReadBasicSetting(UISettings::values.show_add_ons);
822 ReadBasicSetting(UISettings::values.show_compat);
822 ReadBasicSetting(UISettings::values.game_icon_size); 823 ReadBasicSetting(UISettings::values.game_icon_size);
823 ReadBasicSetting(UISettings::values.folder_icon_size); 824 ReadBasicSetting(UISettings::values.folder_icon_size);
824 ReadBasicSetting(UISettings::values.row_1_text_id); 825 ReadBasicSetting(UISettings::values.row_1_text_id);
@@ -1414,6 +1415,7 @@ void Config::SaveUIGamelistValues() {
1414 qt_config->beginGroup(QStringLiteral("UIGameList")); 1415 qt_config->beginGroup(QStringLiteral("UIGameList"));
1415 1416
1416 WriteBasicSetting(UISettings::values.show_add_ons); 1417 WriteBasicSetting(UISettings::values.show_add_ons);
1418 WriteBasicSetting(UISettings::values.show_compat);
1417 WriteBasicSetting(UISettings::values.game_icon_size); 1419 WriteBasicSetting(UISettings::values.game_icon_size);
1418 WriteBasicSetting(UISettings::values.folder_icon_size); 1420 WriteBasicSetting(UISettings::values.folder_icon_size);
1419 WriteBasicSetting(UISettings::values.row_1_text_id); 1421 WriteBasicSetting(UISettings::values.row_1_text_id);
diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp
index 48f71b53c..92e6da6ee 100644
--- a/src/yuzu/configuration/configure_ui.cpp
+++ b/src/yuzu/configuration/configure_ui.cpp
@@ -72,6 +72,7 @@ ConfigureUi::ConfigureUi(Core::System& system_, QWidget* parent)
72 72
73 // Force game list reload if any of the relevant settings are changed. 73 // Force game list reload if any of the relevant settings are changed.
74 connect(ui->show_add_ons, &QCheckBox::stateChanged, this, &ConfigureUi::RequestGameListUpdate); 74 connect(ui->show_add_ons, &QCheckBox::stateChanged, this, &ConfigureUi::RequestGameListUpdate);
75 connect(ui->show_compat, &QCheckBox::stateChanged, this, &ConfigureUi::RequestGameListUpdate);
75 connect(ui->game_icon_size_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, 76 connect(ui->game_icon_size_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
76 &ConfigureUi::RequestGameListUpdate); 77 &ConfigureUi::RequestGameListUpdate);
77 connect(ui->folder_icon_size_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), 78 connect(ui->folder_icon_size_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged),
@@ -109,6 +110,7 @@ void ConfigureUi::ApplyConfiguration() {
109 UISettings::values.theme = 110 UISettings::values.theme =
110 ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString(); 111 ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString();
111 UISettings::values.show_add_ons = ui->show_add_ons->isChecked(); 112 UISettings::values.show_add_ons = ui->show_add_ons->isChecked();
113 UISettings::values.show_compat = ui->show_compat->isChecked();
112 UISettings::values.game_icon_size = ui->game_icon_size_combobox->currentData().toUInt(); 114 UISettings::values.game_icon_size = ui->game_icon_size_combobox->currentData().toUInt();
113 UISettings::values.folder_icon_size = ui->folder_icon_size_combobox->currentData().toUInt(); 115 UISettings::values.folder_icon_size = ui->folder_icon_size_combobox->currentData().toUInt();
114 UISettings::values.row_1_text_id = ui->row_1_text_combobox->currentData().toUInt(); 116 UISettings::values.row_1_text_id = ui->row_1_text_combobox->currentData().toUInt();
@@ -129,6 +131,7 @@ void ConfigureUi::SetConfiguration() {
129 ui->language_combobox->setCurrentIndex( 131 ui->language_combobox->setCurrentIndex(
130 ui->language_combobox->findData(UISettings::values.language)); 132 ui->language_combobox->findData(UISettings::values.language));
131 ui->show_add_ons->setChecked(UISettings::values.show_add_ons.GetValue()); 133 ui->show_add_ons->setChecked(UISettings::values.show_add_ons.GetValue());
134 ui->show_compat->setChecked(UISettings::values.show_compat.GetValue());
132 ui->game_icon_size_combobox->setCurrentIndex( 135 ui->game_icon_size_combobox->setCurrentIndex(
133 ui->game_icon_size_combobox->findData(UISettings::values.game_icon_size.GetValue())); 136 ui->game_icon_size_combobox->findData(UISettings::values.game_icon_size.GetValue()));
134 ui->folder_icon_size_combobox->setCurrentIndex( 137 ui->folder_icon_size_combobox->setCurrentIndex(
diff --git a/src/yuzu/configuration/configure_ui.ui b/src/yuzu/configuration/configure_ui.ui
index a50df7f6f..f0b719ba3 100644
--- a/src/yuzu/configuration/configure_ui.ui
+++ b/src/yuzu/configuration/configure_ui.ui
@@ -77,6 +77,13 @@
77 <item> 77 <item>
78 <layout class="QVBoxLayout" name="GeneralVerticalLayout"> 78 <layout class="QVBoxLayout" name="GeneralVerticalLayout">
79 <item> 79 <item>
80 <widget class="QCheckBox" name="show_compat">
81 <property name="text">
82 <string>Show Compatibility List</string>
83 </property>
84 </widget>
85 </item>
86 <item>
80 <widget class="QCheckBox" name="show_add_ons"> 87 <widget class="QCheckBox" name="show_add_ons">
81 <property name="text"> 88 <property name="text">
82 <string>Show Add-Ons Column</string> 89 <string>Show Add-Ons Column</string>
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index b127badc2..d6adfca16 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -335,6 +335,7 @@ GameList::GameList(FileSys::VirtualFilesystem vfs_, FileSys::ManualContentProvid
335 RetranslateUI(); 335 RetranslateUI();
336 336
337 tree_view->setColumnHidden(COLUMN_ADD_ONS, !UISettings::values.show_add_ons); 337 tree_view->setColumnHidden(COLUMN_ADD_ONS, !UISettings::values.show_add_ons);
338 tree_view->setColumnHidden(COLUMN_COMPATIBILITY, !UISettings::values.show_compat);
338 item_model->setSortRole(GameListItemPath::SortRole); 339 item_model->setSortRole(GameListItemPath::SortRole);
339 340
340 connect(main_window, &GMainWindow::UpdateThemedIcons, this, &GameList::OnUpdateThemedIcons); 341 connect(main_window, &GMainWindow::UpdateThemedIcons, this, &GameList::OnUpdateThemedIcons);
@@ -786,6 +787,7 @@ void GameList::PopulateAsync(QVector<UISettings::GameDir>& game_dirs) {
786 787
787 // Update the columns in case UISettings has changed 788 // Update the columns in case UISettings has changed
788 tree_view->setColumnHidden(COLUMN_ADD_ONS, !UISettings::values.show_add_ons); 789 tree_view->setColumnHidden(COLUMN_ADD_ONS, !UISettings::values.show_add_ons);
790 tree_view->setColumnHidden(COLUMN_COMPATIBILITY, !UISettings::values.show_compat);
789 791
790 // Delete any rows that might already exist if we're repopulating 792 // Delete any rows that might already exist if we're repopulating
791 item_model->removeRows(0, item_model->rowCount()); 793 item_model->removeRows(0, item_model->rowCount());
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h
index 753797efc..4f5b2a99d 100644
--- a/src/yuzu/uisettings.h
+++ b/src/yuzu/uisettings.h
@@ -129,6 +129,9 @@ struct Values {
129 Settings::Setting<bool> favorites_expanded{true, "favorites_expanded"}; 129 Settings::Setting<bool> favorites_expanded{true, "favorites_expanded"};
130 QVector<u64> favorited_ids; 130 QVector<u64> favorited_ids;
131 131
132 // Compatibility List
133 Settings::Setting<bool> show_compat{false, "show_compat"};
134
132 bool configuration_applied; 135 bool configuration_applied;
133 bool reset_to_defaults; 136 bool reset_to_defaults;
134 Settings::Setting<bool> disable_web_applet{true, "disable_web_applet"}; 137 Settings::Setting<bool> disable_web_applet{true, "disable_web_applet"};