NVFlinger: Lock race condition between CPU, Host Timing, VSync.
This commit is contained in:
parent
3902067008
commit
cc3aa95926
|
@ -36,10 +36,12 @@ NVFlinger::NVFlinger(Core::System& system) : system(system) {
|
||||||
displays.emplace_back(2, "Edid", system);
|
displays.emplace_back(2, "Edid", system);
|
||||||
displays.emplace_back(3, "Internal", system);
|
displays.emplace_back(3, "Internal", system);
|
||||||
displays.emplace_back(4, "Null", system);
|
displays.emplace_back(4, "Null", system);
|
||||||
|
guard = std::make_shared<std::mutex>();
|
||||||
|
|
||||||
// Schedule the screen composition events
|
// Schedule the screen composition events
|
||||||
composition_event =
|
composition_event =
|
||||||
Core::Timing::CreateEvent("ScreenComposition", [this](u64 userdata, s64 ns_late) {
|
Core::Timing::CreateEvent("ScreenComposition", [this](u64 userdata, s64 ns_late) {
|
||||||
|
Lock();
|
||||||
Compose();
|
Compose();
|
||||||
const auto ticks = GetNextTicks();
|
const auto ticks = GetNextTicks();
|
||||||
this->system.CoreTiming().ScheduleEvent(std::max<s64>(0LL, ticks - ns_late),
|
this->system.CoreTiming().ScheduleEvent(std::max<s64>(0LL, ticks - ns_late),
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
@ -79,6 +80,10 @@ public:
|
||||||
|
|
||||||
s64 GetNextTicks() const;
|
s64 GetNextTicks() const;
|
||||||
|
|
||||||
|
std::unique_lock<std::mutex> Lock() {
|
||||||
|
return std::unique_lock{*guard};
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Finds the display identified by the specified ID.
|
/// Finds the display identified by the specified ID.
|
||||||
VI::Display* FindDisplay(u64 display_id);
|
VI::Display* FindDisplay(u64 display_id);
|
||||||
|
@ -108,6 +113,8 @@ private:
|
||||||
/// Event that handles screen composition.
|
/// Event that handles screen composition.
|
||||||
std::shared_ptr<Core::Timing::EventType> composition_event;
|
std::shared_ptr<Core::Timing::EventType> composition_event;
|
||||||
|
|
||||||
|
std::shared_ptr<std::mutex> guard;
|
||||||
|
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -511,6 +511,7 @@ private:
|
||||||
LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id,
|
LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id,
|
||||||
static_cast<u32>(transaction), flags);
|
static_cast<u32>(transaction), flags);
|
||||||
|
|
||||||
|
nv_flinger->Lock();
|
||||||
auto& buffer_queue = nv_flinger->FindBufferQueue(id);
|
auto& buffer_queue = nv_flinger->FindBufferQueue(id);
|
||||||
|
|
||||||
switch (transaction) {
|
switch (transaction) {
|
||||||
|
@ -550,6 +551,7 @@ private:
|
||||||
[=](std::shared_ptr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx,
|
[=](std::shared_ptr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx,
|
||||||
Kernel::ThreadWakeupReason reason) {
|
Kernel::ThreadWakeupReason reason) {
|
||||||
// Repeat TransactParcel DequeueBuffer when a buffer is available
|
// Repeat TransactParcel DequeueBuffer when a buffer is available
|
||||||
|
nv_flinger->Lock();
|
||||||
auto& buffer_queue = nv_flinger->FindBufferQueue(id);
|
auto& buffer_queue = nv_flinger->FindBufferQueue(id);
|
||||||
auto result = buffer_queue.DequeueBuffer(width, height);
|
auto result = buffer_queue.DequeueBuffer(width, height);
|
||||||
ASSERT_MSG(result != std::nullopt, "Could not dequeue buffer.");
|
ASSERT_MSG(result != std::nullopt, "Could not dequeue buffer.");
|
||||||
|
|
Reference in New Issue