summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/kernel/process.cpp2
-rw-r--r--src/core/hle/kernel/process.h2
-rw-r--r--src/core/hle/kernel/readable_event.cpp2
-rw-r--r--src/core/hle/kernel/readable_event.h2
-rw-r--r--src/core/hle/kernel/server_port.cpp2
-rw-r--r--src/core/hle/kernel/server_port.h2
-rw-r--r--src/core/hle/kernel/server_session.cpp2
-rw-r--r--src/core/hle/kernel/server_session.h2
-rw-r--r--src/core/hle/kernel/shared_memory.cpp11
-rw-r--r--src/core/hle/kernel/shared_memory.h10
-rw-r--r--src/core/hle/kernel/svc.cpp2
-rw-r--r--src/core/hle/kernel/thread.cpp12
-rw-r--r--src/core/hle/kernel/thread.h6
-rw-r--r--src/core/hle/kernel/wait_object.h2
-rw-r--r--src/core/hle/service/am/am.cpp84
-rw-r--r--src/core/hle/service/am/am.h15
-rw-r--r--src/video_core/CMakeLists.txt4
-rw-r--r--src/video_core/renderer_vulkan/vk_swapchain.cpp210
-rw-r--r--src/video_core/renderer_vulkan/vk_swapchain.h92
-rw-r--r--src/yuzu/applets/profile_select.cpp5
-rw-r--r--src/yuzu/applets/software_keyboard.cpp14
-rw-r--r--src/yuzu/debugger/profiler.cpp1
-rw-r--r--src/yuzu/debugger/profiler.h9
23 files changed, 418 insertions, 75 deletions
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 52f253d1e..041267318 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -257,7 +257,7 @@ void Process::Acquire(Thread* thread) {
257 ASSERT_MSG(!ShouldWait(thread), "Object unavailable!"); 257 ASSERT_MSG(!ShouldWait(thread), "Object unavailable!");
258} 258}
259 259
260bool Process::ShouldWait(Thread* thread) const { 260bool Process::ShouldWait(const Thread* thread) const {
261 return !is_signaled; 261 return !is_signaled;
262} 262}
263 263
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index f9ddc937c..f060f2a3b 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -251,7 +251,7 @@ private:
251 ~Process() override; 251 ~Process() override;
252 252
253 /// Checks if the specified thread should wait until this process is available. 253 /// Checks if the specified thread should wait until this process is available.
254 bool ShouldWait(Thread* thread) const override; 254 bool ShouldWait(const Thread* thread) const override;
255 255
256 /// Acquires/locks this process for the specified thread if it's available. 256 /// Acquires/locks this process for the specified thread if it's available.
257 void Acquire(Thread* thread) override; 257 void Acquire(Thread* thread) override;
diff --git a/src/core/hle/kernel/readable_event.cpp b/src/core/hle/kernel/readable_event.cpp
index 0e5083f70..c2b798a4e 100644
--- a/src/core/hle/kernel/readable_event.cpp
+++ b/src/core/hle/kernel/readable_event.cpp
@@ -14,7 +14,7 @@ namespace Kernel {
14ReadableEvent::ReadableEvent(KernelCore& kernel) : WaitObject{kernel} {} 14ReadableEvent::ReadableEvent(KernelCore& kernel) : WaitObject{kernel} {}
15ReadableEvent::~ReadableEvent() = default; 15ReadableEvent::~ReadableEvent() = default;
16 16
17bool ReadableEvent::ShouldWait(Thread* thread) const { 17bool ReadableEvent::ShouldWait(const Thread* thread) const {
18 return !signaled; 18 return !signaled;
19} 19}
20 20
diff --git a/src/core/hle/kernel/readable_event.h b/src/core/hle/kernel/readable_event.h
index 77a9c362c..2eb9dcbb7 100644
--- a/src/core/hle/kernel/readable_event.h
+++ b/src/core/hle/kernel/readable_event.h
@@ -36,7 +36,7 @@ public:
36 return HANDLE_TYPE; 36 return HANDLE_TYPE;
37 } 37 }
38 38
39 bool ShouldWait(Thread* thread) const override; 39 bool ShouldWait(const Thread* thread) const override;
40 void Acquire(Thread* thread) override; 40 void Acquire(Thread* thread) override;
41 41
42 /// Unconditionally clears the readable event's state. 42 /// Unconditionally clears the readable event's state.
diff --git a/src/core/hle/kernel/server_port.cpp b/src/core/hle/kernel/server_port.cpp
index 0e1515c89..708fdf9e1 100644
--- a/src/core/hle/kernel/server_port.cpp
+++ b/src/core/hle/kernel/server_port.cpp
@@ -30,7 +30,7 @@ void ServerPort::AppendPendingSession(SharedPtr<ServerSession> pending_session)
30 pending_sessions.push_back(std::move(pending_session)); 30 pending_sessions.push_back(std::move(pending_session));
31} 31}
32 32
33bool ServerPort::ShouldWait(Thread* thread) const { 33bool ServerPort::ShouldWait(const Thread* thread) const {
34 // If there are no pending sessions, we wait until a new one is added. 34 // If there are no pending sessions, we wait until a new one is added.
35 return pending_sessions.empty(); 35 return pending_sessions.empty();
36} 36}
diff --git a/src/core/hle/kernel/server_port.h b/src/core/hle/kernel/server_port.h
index 9bc667cf2..76293cb8b 100644
--- a/src/core/hle/kernel/server_port.h
+++ b/src/core/hle/kernel/server_port.h
@@ -75,7 +75,7 @@ public:
75 /// waiting to be accepted by this port. 75 /// waiting to be accepted by this port.
76 void AppendPendingSession(SharedPtr<ServerSession> pending_session); 76 void AppendPendingSession(SharedPtr<ServerSession> pending_session);
77 77
78 bool ShouldWait(Thread* thread) const override; 78 bool ShouldWait(const Thread* thread) const override;
79 void Acquire(Thread* thread) override; 79 void Acquire(Thread* thread) override;
80 80
81private: 81private:
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp
index 4d8a337a7..40cec143e 100644
--- a/src/core/hle/kernel/server_session.cpp
+++ b/src/core/hle/kernel/server_session.cpp
@@ -46,7 +46,7 @@ ResultVal<SharedPtr<ServerSession>> ServerSession::Create(KernelCore& kernel, st
46 return MakeResult(std::move(server_session)); 46 return MakeResult(std::move(server_session));
47} 47}
48 48
49bool ServerSession::ShouldWait(Thread* thread) const { 49bool ServerSession::ShouldWait(const Thread* thread) const {
50 // Closed sessions should never wait, an error will be returned from svcReplyAndReceive. 50 // Closed sessions should never wait, an error will be returned from svcReplyAndReceive.
51 if (parent->client == nullptr) 51 if (parent->client == nullptr)
52 return false; 52 return false;
diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h
index aea4ccfeb..79b84bade 100644
--- a/src/core/hle/kernel/server_session.h
+++ b/src/core/hle/kernel/server_session.h
@@ -82,7 +82,7 @@ public:
82 */ 82 */
83 ResultCode HandleSyncRequest(SharedPtr<Thread> thread); 83 ResultCode HandleSyncRequest(SharedPtr<Thread> thread);
84 84
85 bool ShouldWait(Thread* thread) const override; 85 bool ShouldWait(const Thread* thread) const override;
86 86
87 void Acquire(Thread* thread) override; 87 void Acquire(Thread* thread) override;
88 88
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index 62861da36..f15c5ee36 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -9,7 +9,6 @@
9#include "core/hle/kernel/errors.h" 9#include "core/hle/kernel/errors.h"
10#include "core/hle/kernel/kernel.h" 10#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/shared_memory.h" 11#include "core/hle/kernel/shared_memory.h"
12#include "core/memory.h"
13 12
14namespace Kernel { 13namespace Kernel {
15 14
@@ -119,7 +118,15 @@ ResultCode SharedMemory::Map(Process& target_process, VAddr address, MemoryPermi
119 ConvertPermissions(permissions)); 118 ConvertPermissions(permissions));
120} 119}
121 120
122ResultCode SharedMemory::Unmap(Process& target_process, VAddr address) { 121ResultCode SharedMemory::Unmap(Process& target_process, VAddr address, u64 unmap_size) {
122 if (unmap_size != size) {
123 LOG_ERROR(Kernel,
124 "Invalid size passed to Unmap. Size must be equal to the size of the "
125 "memory managed. Shared memory size=0x{:016X}, Unmap size=0x{:016X}",
126 size, unmap_size);
127 return ERR_INVALID_SIZE;
128 }
129
123 // TODO(Subv): Verify what happens if the application tries to unmap an address that is not 130 // TODO(Subv): Verify what happens if the application tries to unmap an address that is not
124 // mapped to a SharedMemory. 131 // mapped to a SharedMemory.
125 return target_process.VMManager().UnmapRange(address, size); 132 return target_process.VMManager().UnmapRange(address, size);
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h
index dab2a6bea..37e18c443 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -104,11 +104,17 @@ public:
104 104
105 /** 105 /**
106 * Unmaps a shared memory block from the specified address in system memory 106 * Unmaps a shared memory block from the specified address in system memory
107 *
107 * @param target_process Process from which to unmap the memory block. 108 * @param target_process Process from which to unmap the memory block.
108 * @param address Address in system memory where the shared memory block is mapped 109 * @param address Address in system memory where the shared memory block is mapped.
110 * @param unmap_size The amount of bytes to unmap from this shared memory instance.
111 *
109 * @return Result code of the unmap operation 112 * @return Result code of the unmap operation
113 *
114 * @pre The given size to unmap must be the same size as the amount of memory managed by
115 * the SharedMemory instance itself, otherwise ERR_INVALID_SIZE will be returned.
110 */ 116 */
111 ResultCode Unmap(Process& target_process, VAddr address); 117 ResultCode Unmap(Process& target_process, VAddr address, u64 unmap_size);
112 118
113 /** 119 /**
114 * Gets a pointer to the shared memory block 120 * Gets a pointer to the shared memory block
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 23c768f57..ab10db3df 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -1140,7 +1140,7 @@ static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64
1140 return ERR_INVALID_MEMORY_RANGE; 1140 return ERR_INVALID_MEMORY_RANGE;
1141 } 1141 }
1142 1142
1143 return shared_memory->Unmap(*current_process, addr); 1143 return shared_memory->Unmap(*current_process, addr, size);
1144} 1144}
1145 1145
1146static ResultCode QueryProcessMemory(VAddr memory_info_address, VAddr page_info_address, 1146static ResultCode QueryProcessMemory(VAddr memory_info_address, VAddr page_info_address,
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 3ec3710b2..1b891f632 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -28,7 +28,7 @@
28 28
29namespace Kernel { 29namespace Kernel {
30 30
31bool Thread::ShouldWait(Thread* thread) const { 31bool Thread::ShouldWait(const Thread* thread) const {
32 return status != ThreadStatus::Dead; 32 return status != ThreadStatus::Dead;
33} 33}
34 34
@@ -233,16 +233,16 @@ void Thread::SetWaitSynchronizationOutput(s32 output) {
233 context.cpu_registers[1] = output; 233 context.cpu_registers[1] = output;
234} 234}
235 235
236s32 Thread::GetWaitObjectIndex(WaitObject* object) const { 236s32 Thread::GetWaitObjectIndex(const WaitObject* object) const {
237 ASSERT_MSG(!wait_objects.empty(), "Thread is not waiting for anything"); 237 ASSERT_MSG(!wait_objects.empty(), "Thread is not waiting for anything");
238 auto match = std::find(wait_objects.rbegin(), wait_objects.rend(), object); 238 const auto match = std::find(wait_objects.rbegin(), wait_objects.rend(), object);
239 return static_cast<s32>(std::distance(match, wait_objects.rend()) - 1); 239 return static_cast<s32>(std::distance(match, wait_objects.rend()) - 1);
240} 240}
241 241
242VAddr Thread::GetCommandBufferAddress() const { 242VAddr Thread::GetCommandBufferAddress() const {
243 // Offset from the start of TLS at which the IPC command buffer begins. 243 // Offset from the start of TLS at which the IPC command buffer begins.
244 static constexpr int CommandHeaderOffset = 0x80; 244 constexpr u64 command_header_offset = 0x80;
245 return GetTLSAddress() + CommandHeaderOffset; 245 return GetTLSAddress() + command_header_offset;
246} 246}
247 247
248void Thread::SetStatus(ThreadStatus new_status) { 248void Thread::SetStatus(ThreadStatus new_status) {
@@ -371,7 +371,7 @@ void Thread::ChangeScheduler() {
371 system.CpuCore(processor_id).PrepareReschedule(); 371 system.CpuCore(processor_id).PrepareReschedule();
372} 372}
373 373
374bool Thread::AllWaitObjectsReady() { 374bool Thread::AllWaitObjectsReady() const {
375 return std::none_of( 375 return std::none_of(
376 wait_objects.begin(), wait_objects.end(), 376 wait_objects.begin(), wait_objects.end(),
377 [this](const SharedPtr<WaitObject>& object) { return object->ShouldWait(this); }); 377 [this](const SharedPtr<WaitObject>& object) { return object->ShouldWait(this); });
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 9c684758c..73e5d1bb4 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -111,7 +111,7 @@ public:
111 return HANDLE_TYPE; 111 return HANDLE_TYPE;
112 } 112 }
113 113
114 bool ShouldWait(Thread* thread) const override; 114 bool ShouldWait(const Thread* thread) const override;
115 void Acquire(Thread* thread) override; 115 void Acquire(Thread* thread) override;
116 116
117 /** 117 /**
@@ -205,7 +205,7 @@ public:
205 * object in the list. 205 * object in the list.
206 * @param object Object to query the index of. 206 * @param object Object to query the index of.
207 */ 207 */
208 s32 GetWaitObjectIndex(WaitObject* object) const; 208 s32 GetWaitObjectIndex(const WaitObject* object) const;
209 209
210 /** 210 /**
211 * Stops a thread, invalidating it from further use 211 * Stops a thread, invalidating it from further use
@@ -299,7 +299,7 @@ public:
299 } 299 }
300 300
301 /// Determines whether all the objects this thread is waiting on are ready. 301 /// Determines whether all the objects this thread is waiting on are ready.
302 bool AllWaitObjectsReady(); 302 bool AllWaitObjectsReady() const;
303 303
304 const MutexWaitingThreads& GetMutexWaitingThreads() const { 304 const MutexWaitingThreads& GetMutexWaitingThreads() const {
305 return wait_mutex_threads; 305 return wait_mutex_threads;
diff --git a/src/core/hle/kernel/wait_object.h b/src/core/hle/kernel/wait_object.h
index 5987fb971..04464a51a 100644
--- a/src/core/hle/kernel/wait_object.h
+++ b/src/core/hle/kernel/wait_object.h
@@ -24,7 +24,7 @@ public:
24 * @param thread The thread about which we're deciding. 24 * @param thread The thread about which we're deciding.
25 * @return True if the current thread should wait due to this object being unavailable 25 * @return True if the current thread should wait due to this object being unavailable
26 */ 26 */
27 virtual bool ShouldWait(Thread* thread) const = 0; 27 virtual bool ShouldWait(const Thread* thread) const = 0;
28 28
29 /// Acquire/lock the object for the specified thread if it is available 29 /// Acquire/lock the object for the specified thread if it is available
30 virtual void Acquire(Thread* thread) = 0; 30 virtual void Acquire(Thread* thread) = 0;
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 9c44e27c6..d31ab7970 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -239,8 +239,8 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger
239 {0, nullptr, "Exit"}, 239 {0, nullptr, "Exit"},
240 {1, &ISelfController::LockExit, "LockExit"}, 240 {1, &ISelfController::LockExit, "LockExit"},
241 {2, &ISelfController::UnlockExit, "UnlockExit"}, 241 {2, &ISelfController::UnlockExit, "UnlockExit"},
242 {3, nullptr, "EnterFatalSection"}, 242 {3, &ISelfController::EnterFatalSection, "EnterFatalSection"},
243 {4, nullptr, "LeaveFatalSection"}, 243 {4, &ISelfController::LeaveFatalSection, "LeaveFatalSection"},
244 {9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"}, 244 {9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"},
245 {10, &ISelfController::SetScreenShotPermission, "SetScreenShotPermission"}, 245 {10, &ISelfController::SetScreenShotPermission, "SetScreenShotPermission"},
246 {11, &ISelfController::SetOperationModeChangedNotification, "SetOperationModeChangedNotification"}, 246 {11, &ISelfController::SetOperationModeChangedNotification, "SetOperationModeChangedNotification"},
@@ -285,41 +285,54 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger
285 285
286ISelfController::~ISelfController() = default; 286ISelfController::~ISelfController() = default;
287 287
288void ISelfController::SetFocusHandlingMode(Kernel::HLERequestContext& ctx) { 288void ISelfController::LockExit(Kernel::HLERequestContext& ctx) {
289 // Takes 3 input u8s with each field located immediately after the previous
290 // u8, these are bool flags. No output.
291 LOG_WARNING(Service_AM, "(STUBBED) called"); 289 LOG_WARNING(Service_AM, "(STUBBED) called");
292 290
293 IPC::RequestParser rp{ctx}; 291 IPC::ResponseBuilder rb{ctx, 2};
292 rb.Push(RESULT_SUCCESS);
293}
294 294
295 struct FocusHandlingModeParams { 295void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) {
296 u8 unknown0; 296 LOG_WARNING(Service_AM, "(STUBBED) called");
297 u8 unknown1;
298 u8 unknown2;
299 };
300 auto flags = rp.PopRaw<FocusHandlingModeParams>();
301 297
302 IPC::ResponseBuilder rb{ctx, 2}; 298 IPC::ResponseBuilder rb{ctx, 2};
303 rb.Push(RESULT_SUCCESS); 299 rb.Push(RESULT_SUCCESS);
304} 300}
305 301
306void ISelfController::SetRestartMessageEnabled(Kernel::HLERequestContext& ctx) { 302void ISelfController::EnterFatalSection(Kernel::HLERequestContext& ctx) {
307 LOG_WARNING(Service_AM, "(STUBBED) called"); 303 ++num_fatal_sections_entered;
304 LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", num_fatal_sections_entered);
308 305
309 IPC::ResponseBuilder rb{ctx, 2}; 306 IPC::ResponseBuilder rb{ctx, 2};
310 rb.Push(RESULT_SUCCESS); 307 rb.Push(RESULT_SUCCESS);
311} 308}
312 309
313void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx) { 310void ISelfController::LeaveFatalSection(Kernel::HLERequestContext& ctx) {
314 IPC::RequestParser rp{ctx}; 311 LOG_DEBUG(Service_AM, "called.");
315 312
316 bool flag = rp.Pop<bool>(); 313 // Entry and exit of fatal sections must be balanced.
317 LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag); 314 if (num_fatal_sections_entered == 0) {
315 IPC::ResponseBuilder rb{ctx, 2};
316 rb.Push(ResultCode{ErrorModule::AM, 512});
317 return;
318 }
319
320 --num_fatal_sections_entered;
318 321
319 IPC::ResponseBuilder rb{ctx, 2}; 322 IPC::ResponseBuilder rb{ctx, 2};
320 rb.Push(RESULT_SUCCESS); 323 rb.Push(RESULT_SUCCESS);
321} 324}
322 325
326void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) {
327 LOG_WARNING(Service_AM, "(STUBBED) called");
328
329 launchable_event.writable->Signal();
330
331 IPC::ResponseBuilder rb{ctx, 2, 1};
332 rb.Push(RESULT_SUCCESS);
333 rb.PushCopyObjects(launchable_event.readable);
334}
335
323void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) { 336void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) {
324 LOG_WARNING(Service_AM, "(STUBBED) called"); 337 LOG_WARNING(Service_AM, "(STUBBED) called");
325 338
@@ -337,40 +350,51 @@ void ISelfController::SetOperationModeChangedNotification(Kernel::HLERequestCont
337 rb.Push(RESULT_SUCCESS); 350 rb.Push(RESULT_SUCCESS);
338} 351}
339 352
340void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx) { 353void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx) {
341 // Takes 3 input u8s with each field located immediately after the previous
342 // u8, these are bool flags. No output.
343 IPC::RequestParser rp{ctx}; 354 IPC::RequestParser rp{ctx};
344 355
345 bool enabled = rp.Pop<bool>(); 356 bool flag = rp.Pop<bool>();
346 LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled); 357 LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
347 358
348 IPC::ResponseBuilder rb{ctx, 2}; 359 IPC::ResponseBuilder rb{ctx, 2};
349 rb.Push(RESULT_SUCCESS); 360 rb.Push(RESULT_SUCCESS);
350} 361}
351 362
352void ISelfController::LockExit(Kernel::HLERequestContext& ctx) { 363void ISelfController::SetFocusHandlingMode(Kernel::HLERequestContext& ctx) {
364 // Takes 3 input u8s with each field located immediately after the previous
365 // u8, these are bool flags. No output.
353 LOG_WARNING(Service_AM, "(STUBBED) called"); 366 LOG_WARNING(Service_AM, "(STUBBED) called");
354 367
368 IPC::RequestParser rp{ctx};
369
370 struct FocusHandlingModeParams {
371 u8 unknown0;
372 u8 unknown1;
373 u8 unknown2;
374 };
375 auto flags = rp.PopRaw<FocusHandlingModeParams>();
376
355 IPC::ResponseBuilder rb{ctx, 2}; 377 IPC::ResponseBuilder rb{ctx, 2};
356 rb.Push(RESULT_SUCCESS); 378 rb.Push(RESULT_SUCCESS);
357} 379}
358 380
359void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) { 381void ISelfController::SetRestartMessageEnabled(Kernel::HLERequestContext& ctx) {
360 LOG_WARNING(Service_AM, "(STUBBED) called"); 382 LOG_WARNING(Service_AM, "(STUBBED) called");
361 383
362 IPC::ResponseBuilder rb{ctx, 2}; 384 IPC::ResponseBuilder rb{ctx, 2};
363 rb.Push(RESULT_SUCCESS); 385 rb.Push(RESULT_SUCCESS);
364} 386}
365 387
366void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) { 388void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx) {
367 LOG_WARNING(Service_AM, "(STUBBED) called"); 389 // Takes 3 input u8s with each field located immediately after the previous
390 // u8, these are bool flags. No output.
391 IPC::RequestParser rp{ctx};
368 392
369 launchable_event.writable->Signal(); 393 bool enabled = rp.Pop<bool>();
394 LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled);
370 395
371 IPC::ResponseBuilder rb{ctx, 2, 1}; 396 IPC::ResponseBuilder rb{ctx, 2};
372 rb.Push(RESULT_SUCCESS); 397 rb.Push(RESULT_SUCCESS);
373 rb.PushCopyObjects(launchable_event.readable);
374} 398}
375 399
376void ISelfController::SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx) { 400void ISelfController::SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx) {
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 565dd8e9e..991b7d47c 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -117,17 +117,19 @@ public:
117 ~ISelfController() override; 117 ~ISelfController() override;
118 118
119private: 119private:
120 void SetFocusHandlingMode(Kernel::HLERequestContext& ctx);
121 void SetRestartMessageEnabled(Kernel::HLERequestContext& ctx);
122 void SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx);
123 void SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx);
124 void SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx);
125 void LockExit(Kernel::HLERequestContext& ctx); 120 void LockExit(Kernel::HLERequestContext& ctx);
126 void UnlockExit(Kernel::HLERequestContext& ctx); 121 void UnlockExit(Kernel::HLERequestContext& ctx);
122 void EnterFatalSection(Kernel::HLERequestContext& ctx);
123 void LeaveFatalSection(Kernel::HLERequestContext& ctx);
127 void GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx); 124 void GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx);
125 void SetScreenShotPermission(Kernel::HLERequestContext& ctx);
126 void SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx);
127 void SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx);
128 void SetFocusHandlingMode(Kernel::HLERequestContext& ctx);
129 void SetRestartMessageEnabled(Kernel::HLERequestContext& ctx);
130 void SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx);
128 void SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx); 131 void SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx);
129 void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx); 132 void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx);
130 void SetScreenShotPermission(Kernel::HLERequestContext& ctx);
131 void SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx); 133 void SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx);
132 void SetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx); 134 void SetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx);
133 void GetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx); 135 void GetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx);
@@ -135,6 +137,7 @@ private:
135 std::shared_ptr<NVFlinger::NVFlinger> nvflinger; 137 std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
136 Kernel::EventPair launchable_event; 138 Kernel::EventPair launchable_event;
137 u32 idle_time_detection_extension = 0; 139 u32 idle_time_detection_extension = 0;
140 u64 num_fatal_sections_entered = 0;
138}; 141};
139 142
140class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { 143class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 14b76680f..44c761d3e 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -128,7 +128,9 @@ if (ENABLE_VULKAN)
128 renderer_vulkan/vk_scheduler.cpp 128 renderer_vulkan/vk_scheduler.cpp
129 renderer_vulkan/vk_scheduler.h 129 renderer_vulkan/vk_scheduler.h
130 renderer_vulkan/vk_stream_buffer.cpp 130 renderer_vulkan/vk_stream_buffer.cpp
131 renderer_vulkan/vk_stream_buffer.h) 131 renderer_vulkan/vk_stream_buffer.h
132 renderer_vulkan/vk_swapchain.cpp
133 renderer_vulkan/vk_swapchain.h)
132 134
133 target_include_directories(video_core PRIVATE ../../externals/Vulkan-Headers/include) 135 target_include_directories(video_core PRIVATE ../../externals/Vulkan-Headers/include)
134 target_compile_definitions(video_core PRIVATE HAS_VULKAN) 136 target_compile_definitions(video_core PRIVATE HAS_VULKAN)
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp
new file mode 100644
index 000000000..08279e562
--- /dev/null
+++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp
@@ -0,0 +1,210 @@
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 <algorithm>
6#include <array>
7#include <limits>
8#include <vector>
9
10#include "common/assert.h"
11#include "common/logging/log.h"
12#include "core/core.h"
13#include "core/frontend/framebuffer_layout.h"
14#include "video_core/renderer_vulkan/declarations.h"
15#include "video_core/renderer_vulkan/vk_device.h"
16#include "video_core/renderer_vulkan/vk_resource_manager.h"
17#include "video_core/renderer_vulkan/vk_swapchain.h"
18
19namespace Vulkan {
20
21namespace {
22vk::SurfaceFormatKHR ChooseSwapSurfaceFormat(const std::vector<vk::SurfaceFormatKHR>& formats) {
23 if (formats.size() == 1 && formats[0].format == vk::Format::eUndefined) {
24 return {vk::Format::eB8G8R8A8Unorm, vk::ColorSpaceKHR::eSrgbNonlinear};
25 }
26 const auto& found = std::find_if(formats.begin(), formats.end(), [](const auto& format) {
27 return format.format == vk::Format::eB8G8R8A8Unorm &&
28 format.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear;
29 });
30 return found != formats.end() ? *found : formats[0];
31}
32
33vk::PresentModeKHR ChooseSwapPresentMode(const std::vector<vk::PresentModeKHR>& modes) {
34 // Mailbox doesn't lock the application like fifo (vsync), prefer it
35 const auto& found = std::find_if(modes.begin(), modes.end(), [](const auto& mode) {
36 return mode == vk::PresentModeKHR::eMailbox;
37 });
38 return found != modes.end() ? *found : vk::PresentModeKHR::eFifo;
39}
40
41vk::Extent2D ChooseSwapExtent(const vk::SurfaceCapabilitiesKHR& capabilities, u32 width,
42 u32 height) {
43 constexpr auto undefined_size{std::numeric_limits<u32>::max()};
44 if (capabilities.currentExtent.width != undefined_size) {
45 return capabilities.currentExtent;
46 }
47 vk::Extent2D extent = {width, height};
48 extent.width = std::max(capabilities.minImageExtent.width,
49 std::min(capabilities.maxImageExtent.width, extent.width));
50 extent.height = std::max(capabilities.minImageExtent.height,
51 std::min(capabilities.maxImageExtent.height, extent.height));
52 return extent;
53}
54} // namespace
55
56VKSwapchain::VKSwapchain(vk::SurfaceKHR surface, const VKDevice& device)
57 : surface{surface}, device{device} {}
58
59VKSwapchain::~VKSwapchain() = default;
60
61void VKSwapchain::Create(u32 width, u32 height) {
62 const auto dev = device.GetLogical();
63 const auto& dld = device.GetDispatchLoader();
64 const auto physical_device = device.GetPhysical();
65
66 const vk::SurfaceCapabilitiesKHR capabilities{
67 physical_device.getSurfaceCapabilitiesKHR(surface, dld)};
68 if (capabilities.maxImageExtent.width == 0 || capabilities.maxImageExtent.height == 0) {
69 return;
70 }
71
72 dev.waitIdle(dld);
73 Destroy();
74
75 CreateSwapchain(capabilities, width, height);
76 CreateSemaphores();
77 CreateImageViews();
78
79 fences.resize(image_count, nullptr);
80}
81
82void VKSwapchain::AcquireNextImage() {
83 const auto dev{device.GetLogical()};
84 const auto& dld{device.GetDispatchLoader()};
85 dev.acquireNextImageKHR(*swapchain, std::numeric_limits<u64>::max(),
86 *present_semaphores[frame_index], {}, &image_index, dld);
87
88 if (auto& fence = fences[image_index]; fence) {
89 fence->Wait();
90 fence->Release();
91 fence = nullptr;
92 }
93}
94
95bool VKSwapchain::Present(vk::Semaphore render_semaphore, VKFence& fence) {
96 const vk::Semaphore present_semaphore{*present_semaphores[frame_index]};
97 const std::array<vk::Semaphore, 2> semaphores{present_semaphore, render_semaphore};
98 const u32 wait_semaphore_count{render_semaphore ? 2U : 1U};
99 const auto& dld{device.GetDispatchLoader()};
100 const auto present_queue{device.GetPresentQueue()};
101 bool recreated = false;
102
103 const vk::PresentInfoKHR present_info(wait_semaphore_count, semaphores.data(), 1,
104 &swapchain.get(), &image_index, {});
105 switch (const auto result = present_queue.presentKHR(&present_info, dld); result) {
106 case vk::Result::eSuccess:
107 break;
108 case vk::Result::eErrorOutOfDateKHR:
109 if (current_width > 0 && current_height > 0) {
110 Create(current_width, current_height);
111 recreated = true;
112 }
113 break;
114 default:
115 LOG_CRITICAL(Render_Vulkan, "Vulkan failed to present swapchain due to {}!",
116 vk::to_string(result));
117 UNREACHABLE();
118 }
119
120 ASSERT(fences[image_index] == nullptr);
121 fences[image_index] = &fence;
122 frame_index = (frame_index + 1) % image_count;
123 return recreated;
124}
125
126bool VKSwapchain::HasFramebufferChanged(const Layout::FramebufferLayout& framebuffer) const {
127 // TODO(Rodrigo): Handle framebuffer pixel format changes
128 return framebuffer.width != current_width || framebuffer.height != current_height;
129}
130
131void VKSwapchain::CreateSwapchain(const vk::SurfaceCapabilitiesKHR& capabilities, u32 width,
132 u32 height) {
133 const auto dev{device.GetLogical()};
134 const auto& dld{device.GetDispatchLoader()};
135 const auto physical_device{device.GetPhysical()};
136
137 const std::vector<vk::SurfaceFormatKHR> formats{
138 physical_device.getSurfaceFormatsKHR(surface, dld)};
139
140 const std::vector<vk::PresentModeKHR> present_modes{
141 physical_device.getSurfacePresentModesKHR(surface, dld)};
142
143 const vk::SurfaceFormatKHR surface_format{ChooseSwapSurfaceFormat(formats)};
144 const vk::PresentModeKHR present_mode{ChooseSwapPresentMode(present_modes)};
145 extent = ChooseSwapExtent(capabilities, width, height);
146
147 current_width = extent.width;
148 current_height = extent.height;
149
150 u32 requested_image_count{capabilities.minImageCount + 1};
151 if (capabilities.maxImageCount > 0 && requested_image_count > capabilities.maxImageCount) {
152 requested_image_count = capabilities.maxImageCount;
153 }
154
155 vk::SwapchainCreateInfoKHR swapchain_ci(
156 {}, surface, requested_image_count, surface_format.format, surface_format.colorSpace,
157 extent, 1, vk::ImageUsageFlagBits::eColorAttachment, {}, {}, {},
158 capabilities.currentTransform, vk::CompositeAlphaFlagBitsKHR::eOpaque, present_mode, false,
159 {});
160
161 const u32 graphics_family{device.GetGraphicsFamily()};
162 const u32 present_family{device.GetPresentFamily()};
163 const std::array<u32, 2> queue_indices{graphics_family, present_family};
164 if (graphics_family != present_family) {
165 swapchain_ci.imageSharingMode = vk::SharingMode::eConcurrent;
166 swapchain_ci.queueFamilyIndexCount = static_cast<u32>(queue_indices.size());
167 swapchain_ci.pQueueFamilyIndices = queue_indices.data();
168 } else {
169 swapchain_ci.imageSharingMode = vk::SharingMode::eExclusive;
170 }
171
172 swapchain = dev.createSwapchainKHRUnique(swapchain_ci, nullptr, dld);
173
174 images = dev.getSwapchainImagesKHR(*swapchain, dld);
175 image_count = static_cast<u32>(images.size());
176 image_format = surface_format.format;
177}
178
179void VKSwapchain::CreateSemaphores() {
180 const auto dev{device.GetLogical()};
181 const auto& dld{device.GetDispatchLoader()};
182
183 present_semaphores.resize(image_count);
184 for (std::size_t i = 0; i < image_count; i++) {
185 present_semaphores[i] = dev.createSemaphoreUnique({}, nullptr, dld);
186 }
187}
188
189void VKSwapchain::CreateImageViews() {
190 const auto dev{device.GetLogical()};
191 const auto& dld{device.GetDispatchLoader()};
192
193 image_views.resize(image_count);
194 for (std::size_t i = 0; i < image_count; i++) {
195 const vk::ImageViewCreateInfo image_view_ci({}, images[i], vk::ImageViewType::e2D,
196 image_format, {},
197 {vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1});
198 image_views[i] = dev.createImageViewUnique(image_view_ci, nullptr, dld);
199 }
200}
201
202void VKSwapchain::Destroy() {
203 frame_index = 0;
204 present_semaphores.clear();
205 framebuffers.clear();
206 image_views.clear();
207 swapchain.reset();
208}
209
210} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.h b/src/video_core/renderer_vulkan/vk_swapchain.h
new file mode 100644
index 000000000..2ad84f185
--- /dev/null
+++ b/src/video_core/renderer_vulkan/vk_swapchain.h
@@ -0,0 +1,92 @@
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 <vector>
8
9#include "common/common_types.h"
10#include "video_core/renderer_vulkan/declarations.h"
11
12namespace Layout {
13struct FramebufferLayout;
14}
15
16namespace Vulkan {
17
18class VKDevice;
19class VKFence;
20
21class VKSwapchain {
22public:
23 explicit VKSwapchain(vk::SurfaceKHR surface, const VKDevice& device);
24 ~VKSwapchain();
25
26 /// Creates (or recreates) the swapchain with a given size.
27 void Create(u32 width, u32 height);
28
29 /// Acquires the next image in the swapchain, waits as needed.
30 void AcquireNextImage();
31
32 /// Presents the rendered image to the swapchain. Returns true when the swapchains had to be
33 /// recreated. Takes responsability for the ownership of fence.
34 bool Present(vk::Semaphore render_semaphore, VKFence& fence);
35
36 /// Returns true when the framebuffer layout has changed.
37 bool HasFramebufferChanged(const Layout::FramebufferLayout& framebuffer) const;
38
39 const vk::Extent2D& GetSize() const {
40 return extent;
41 }
42
43 u32 GetImageCount() const {
44 return image_count;
45 }
46
47 u32 GetImageIndex() const {
48 return image_index;
49 }
50
51 vk::Image GetImageIndex(u32 index) const {
52 return images[index];
53 }
54
55 vk::ImageView GetImageViewIndex(u32 index) const {
56 return *image_views[index];
57 }
58
59 vk::Format GetImageFormat() const {
60 return image_format;
61 }
62
63private:
64 void CreateSwapchain(const vk::SurfaceCapabilitiesKHR& capabilities, u32 width, u32 height);
65 void CreateSemaphores();
66 void CreateImageViews();
67
68 void Destroy();
69
70 const vk::SurfaceKHR surface;
71 const VKDevice& device;
72
73 UniqueSwapchainKHR swapchain;
74
75 u32 image_count{};
76 std::vector<vk::Image> images;
77 std::vector<UniqueImageView> image_views;
78 std::vector<UniqueFramebuffer> framebuffers;
79 std::vector<VKFence*> fences;
80 std::vector<UniqueSemaphore> present_semaphores;
81
82 u32 image_index{};
83 u32 frame_index{};
84
85 vk::Format image_format{};
86 vk::Extent2D extent{};
87
88 u32 current_width{};
89 u32 current_height{};
90};
91
92} // namespace Vulkan
diff --git a/src/yuzu/applets/profile_select.cpp b/src/yuzu/applets/profile_select.cpp
index 730426c16..f95f7fe3c 100644
--- a/src/yuzu/applets/profile_select.cpp
+++ b/src/yuzu/applets/profile_select.cpp
@@ -58,10 +58,7 @@ QtProfileSelectionDialog::QtProfileSelectionDialog(QWidget* parent)
58 58
59 scroll_area = new QScrollArea; 59 scroll_area = new QScrollArea;
60 60
61 buttons = new QDialogButtonBox; 61 buttons = new QDialogButtonBox(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
62 buttons->addButton(tr("Cancel"), QDialogButtonBox::RejectRole);
63 buttons->addButton(tr("OK"), QDialogButtonBox::AcceptRole);
64
65 connect(buttons, &QDialogButtonBox::accepted, this, &QtProfileSelectionDialog::accept); 62 connect(buttons, &QDialogButtonBox::accepted, this, &QtProfileSelectionDialog::accept);
66 connect(buttons, &QDialogButtonBox::rejected, this, &QtProfileSelectionDialog::reject); 63 connect(buttons, &QDialogButtonBox::rejected, this, &QtProfileSelectionDialog::reject);
67 64
diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp
index eddc9c941..f3eb29b25 100644
--- a/src/yuzu/applets/software_keyboard.cpp
+++ b/src/yuzu/applets/software_keyboard.cpp
@@ -75,13 +75,13 @@ QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog(
75 length_label->setText(QStringLiteral("%1/%2").arg(text.size()).arg(parameters.max_length)); 75 length_label->setText(QStringLiteral("%1/%2").arg(text.size()).arg(parameters.max_length));
76 }); 76 });
77 77
78 buttons = new QDialogButtonBox; 78 buttons = new QDialogButtonBox(QDialogButtonBox::Cancel);
79 buttons->addButton(tr("Cancel"), QDialogButtonBox::RejectRole); 79 if (parameters.submit_text.empty()) {
80 buttons->addButton(parameters.submit_text.empty() 80 buttons->addButton(QDialogButtonBox::Ok);
81 ? tr("OK") 81 } else {
82 : QString::fromStdU16String(parameters.submit_text), 82 buttons->addButton(QString::fromStdU16String(parameters.submit_text),
83 QDialogButtonBox::AcceptRole); 83 QDialogButtonBox::AcceptRole);
84 84 }
85 connect(buttons, &QDialogButtonBox::accepted, this, &QtSoftwareKeyboardDialog::accept); 85 connect(buttons, &QDialogButtonBox::accepted, this, &QtSoftwareKeyboardDialog::accept);
86 connect(buttons, &QDialogButtonBox::rejected, this, &QtSoftwareKeyboardDialog::reject); 86 connect(buttons, &QDialogButtonBox::rejected, this, &QtSoftwareKeyboardDialog::reject);
87 layout->addWidget(header_label); 87 layout->addWidget(header_label);
diff --git a/src/yuzu/debugger/profiler.cpp b/src/yuzu/debugger/profiler.cpp
index 8b30e0a85..86e03e46d 100644
--- a/src/yuzu/debugger/profiler.cpp
+++ b/src/yuzu/debugger/profiler.cpp
@@ -7,6 +7,7 @@
7#include <QMouseEvent> 7#include <QMouseEvent>
8#include <QPainter> 8#include <QPainter>
9#include <QString> 9#include <QString>
10#include <QTimer>
10#include "common/common_types.h" 11#include "common/common_types.h"
11#include "common/microprofile.h" 12#include "common/microprofile.h"
12#include "yuzu/debugger/profiler.h" 13#include "yuzu/debugger/profiler.h"
diff --git a/src/yuzu/debugger/profiler.h b/src/yuzu/debugger/profiler.h
index eae1e9e3c..8e69fdb06 100644
--- a/src/yuzu/debugger/profiler.h
+++ b/src/yuzu/debugger/profiler.h
@@ -4,10 +4,11 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <QAbstractItemModel> 7#include <QWidget>
8#include <QDockWidget> 8
9#include <QTimer> 9class QAction;
10#include "common/microprofile.h" 10class QHideEvent;
11class QShowEvent;
11 12
12class MicroProfileDialog : public QWidget { 13class MicroProfileDialog : public QWidget {
13 Q_OBJECT 14 Q_OBJECT