summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar FernandoS272021-10-05 22:57:18 +0200
committerGravatar Fernando Sahmkow2021-10-16 00:22:01 +0200
commit7dca0bc11ddcbbd38b2cc46b5fc8c0842df5f483 (patch)
treeef8f504f007d01072b8ba75d043dd94e68d75384
parentMerge pull request #7182 from Morph1984/system (diff)
downloadyuzu-7dca0bc11ddcbbd38b2cc46b5fc8c0842df5f483.tar.gz
yuzu-7dca0bc11ddcbbd38b2cc46b5fc8c0842df5f483.tar.xz
yuzu-7dca0bc11ddcbbd38b2cc46b5fc8c0842df5f483.zip
NVHost_Ctrl: Force wait if the gpu falls behind too long.
Diffstat (limited to '')
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp11
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.h2
2 files changed, 13 insertions, 0 deletions
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
index 8b4867ca7..8bbb2c06e 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
@@ -92,6 +92,7 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector
92 if (syncpoint_manager.IsSyncpointExpired(params.syncpt_id, params.threshold)) { 92 if (syncpoint_manager.IsSyncpointExpired(params.syncpt_id, params.threshold)) {
93 params.value = syncpoint_manager.GetSyncpointMin(params.syncpt_id); 93 params.value = syncpoint_manager.GetSyncpointMin(params.syncpt_id);
94 std::memcpy(output.data(), &params, sizeof(params)); 94 std::memcpy(output.data(), &params, sizeof(params));
95 events_interface.failed[event_id] = false;
95 return NvResult::Success; 96 return NvResult::Success;
96 } 97 }
97 98
@@ -99,6 +100,7 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector
99 syncpoint_manager.IsSyncpointExpired(params.syncpt_id, params.threshold)) { 100 syncpoint_manager.IsSyncpointExpired(params.syncpt_id, params.threshold)) {
100 params.value = new_value; 101 params.value = new_value;
101 std::memcpy(output.data(), &params, sizeof(params)); 102 std::memcpy(output.data(), &params, sizeof(params));
103 events_interface.failed[event_id] = false;
102 return NvResult::Success; 104 return NvResult::Success;
103 } 105 }
104 106
@@ -117,6 +119,7 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector
117 event.event->GetWritableEvent().Signal(); 119 event.event->GetWritableEvent().Signal();
118 params.value = current_syncpoint_value; 120 params.value = current_syncpoint_value;
119 std::memcpy(output.data(), &params, sizeof(params)); 121 std::memcpy(output.data(), &params, sizeof(params));
122 events_interface.failed[event_id] = false;
120 return NvResult::Success; 123 return NvResult::Success;
121 } 124 }
122 const u32 target_value = current_syncpoint_value - diff; 125 const u32 target_value = current_syncpoint_value - diff;
@@ -146,6 +149,13 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector
146 } 149 }
147 params.value |= event_id; 150 params.value |= event_id;
148 event.event->GetWritableEvent().Clear(); 151 event.event->GetWritableEvent().Clear();
152 if (events_interface.failed[event_id]) {
153 lock.unlock();
154 gpu.WaitFence(params.syncpt_id, target_value);
155 std::memcpy(output.data(), &params, sizeof(params));
156 events_interface.failed[event_id] = false;
157 return NvResult::Success;
158 }
149 gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value); 159 gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value);
150 std::memcpy(output.data(), &params, sizeof(params)); 160 std::memcpy(output.data(), &params, sizeof(params));
151 return NvResult::Timeout; 161 return NvResult::Timeout;
@@ -201,6 +211,7 @@ NvResult nvhost_ctrl::IocCtrlClearEventWait(const std::vector<u8>& input, std::v
201 if (events_interface.status[event_id] == EventState::Waiting) { 211 if (events_interface.status[event_id] == EventState::Waiting) {
202 events_interface.LiberateEvent(event_id); 212 events_interface.LiberateEvent(event_id);
203 } 213 }
214 events_interface.failed[event_id] = true;
204 215
205 syncpoint_manager.RefreshSyncpoint(events_interface.events[event_id].fence.id); 216 syncpoint_manager.RefreshSyncpoint(events_interface.events[event_id].fence.id);
206 217
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h
index e2a1dde5b..a5af5b785 100644
--- a/src/core/hle/service/nvdrv/nvdrv.h
+++ b/src/core/hle/service/nvdrv/nvdrv.h
@@ -49,6 +49,8 @@ struct EventInterface {
49 std::array<EventState, MaxNvEvents> status{}; 49 std::array<EventState, MaxNvEvents> status{};
50 // Tells if an NVEvent is registered or not 50 // Tells if an NVEvent is registered or not
51 std::array<bool, MaxNvEvents> registered{}; 51 std::array<bool, MaxNvEvents> registered{};
52 // Tells the NVEvent that it has failed.
53 std::array<bool, MaxNvEvents> failed{};
52 // When an NVEvent is waiting on GPU interrupt, this is the sync_point 54 // When an NVEvent is waiting on GPU interrupt, this is the sync_point
53 // associated with it. 55 // associated with it.
54 std::array<u32, MaxNvEvents> assigned_syncpt{}; 56 std::array<u32, MaxNvEvents> assigned_syncpt{};