summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp30
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.h5
-rw-r--r--src/video_core/gpu.cpp5
4 files changed, 35 insertions, 6 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 54de1dc94..3575a3cb3 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -121,6 +121,7 @@ else()
121 121
122 if (ARCHITECTURE_x86_64) 122 if (ARCHITECTURE_x86_64)
123 add_compile_options("-mcx16") 123 add_compile_options("-mcx16")
124 add_compile_options("-fwrapv")
124 endif() 125 endif()
125 126
126 if (APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL Clang) 127 if (APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL Clang)
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
index abde2a6d3..0e22d9273 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
@@ -52,6 +52,8 @@ NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>&
52 return IocCtrlEventRegister(input, output); 52 return IocCtrlEventRegister(input, output);
53 case 0x20: 53 case 0x20:
54 return IocCtrlEventUnregister(input, output); 54 return IocCtrlEventUnregister(input, output);
55 case 0x21:
56 return IocCtrlEventUnregisterBatch(input, output);
55 } 57 }
56 break; 58 break;
57 default: 59 default:
@@ -249,6 +251,25 @@ NvResult nvhost_ctrl::IocCtrlEventUnregister(const std::vector<u8>& input,
249 return FreeEvent(event_id); 251 return FreeEvent(event_id);
250} 252}
251 253
254NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(const std::vector<u8>& input,
255 std::vector<u8>& output) {
256 IocCtrlEventUnregisterBatchParams params{};
257 std::memcpy(&params, input.data(), sizeof(params));
258 u64 event_mask = params.user_events;
259 LOG_DEBUG(Service_NVDRV, " called, event_mask: {:X}", event_mask);
260
261 auto lock = NvEventsLock();
262 while (event_mask != 0) {
263 const u64 event_id = std::countr_zero(event_mask);
264 event_mask &= ~(1ULL << event_id);
265 const auto result = FreeEvent(static_cast<u32>(event_id));
266 if (result != NvResult::Success) {
267 return result;
268 }
269 }
270 return NvResult::Success;
271}
272
252NvResult nvhost_ctrl::IocCtrlClearEventWait(const std::vector<u8>& input, std::vector<u8>& output) { 273NvResult nvhost_ctrl::IocCtrlClearEventWait(const std::vector<u8>& input, std::vector<u8>& output) {
253 IocCtrlEventClearParams params{}; 274 IocCtrlEventClearParams params{};
254 std::memcpy(&params, input.data(), sizeof(params)); 275 std::memcpy(&params, input.data(), sizeof(params));
@@ -362,10 +383,11 @@ u32 nvhost_ctrl::FindFreeNvEvent(u32 syncpoint_id) {
362} 383}
363 384
364void nvhost_ctrl::SignalNvEvent(u32 syncpoint_id, u32 value) { 385void nvhost_ctrl::SignalNvEvent(u32 syncpoint_id, u32 value) {
365 const u32 max = MaxNvEvents - std::countl_zero(events_mask); 386 u64 signal_mask = events_mask;
366 const u32 min = std::countr_zero(events_mask); 387 while (signal_mask != 0) {
367 for (u32 i = min; i < max; i++) { 388 const u64 event_id = std::countr_zero(signal_mask);
368 auto& event = events[i]; 389 signal_mask &= ~(1ULL << event_id);
390 auto& event = events[event_id];
369 if (event.assigned_syncpt != syncpoint_id || event.assigned_value != value) { 391 if (event.assigned_syncpt != syncpoint_id || event.assigned_value != value) {
370 continue; 392 continue;
371 } 393 }
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
index f2fc5d047..9bd10257b 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
@@ -177,16 +177,17 @@ private:
177 static_assert(sizeof(IocCtrlEventUnregisterParams) == 4, 177 static_assert(sizeof(IocCtrlEventUnregisterParams) == 4,
178 "IocCtrlEventUnregisterParams is incorrect size"); 178 "IocCtrlEventUnregisterParams is incorrect size");
179 179
180 struct IocCtrlEventKill { 180 struct IocCtrlEventUnregisterBatchParams {
181 u64_le user_events{}; 181 u64_le user_events{};
182 }; 182 };
183 static_assert(sizeof(IocCtrlEventKill) == 8, "IocCtrlEventKill is incorrect size"); 183 static_assert(sizeof(IocCtrlEventUnregisterBatchParams) == 8, "IocCtrlEventKill is incorrect size");
184 184
185 NvResult NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output); 185 NvResult NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output);
186 NvResult IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output, 186 NvResult IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output,
187 bool is_allocation); 187 bool is_allocation);
188 NvResult IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output); 188 NvResult IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output);
189 NvResult IocCtrlEventUnregister(const std::vector<u8>& input, std::vector<u8>& output); 189 NvResult IocCtrlEventUnregister(const std::vector<u8>& input, std::vector<u8>& output);
190 NvResult IocCtrlEventUnregisterBatch(const std::vector<u8>& input, std::vector<u8>& output);
190 NvResult IocCtrlClearEventWait(const std::vector<u8>& input, std::vector<u8>& output); 191 NvResult IocCtrlClearEventWait(const std::vector<u8>& input, std::vector<u8>& output);
191 192
192 NvResult FreeEvent(u32 slot); 193 NvResult FreeEvent(u32 slot);
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp
index 80a1c69e0..8c0ff0094 100644
--- a/src/video_core/gpu.cpp
+++ b/src/video_core/gpu.cpp
@@ -249,6 +249,11 @@ struct GPU::Impl {
249 249
250 void RegisterSyncptInterrupt(u32 syncpoint_id, u32 value) { 250 void RegisterSyncptInterrupt(u32 syncpoint_id, u32 value) {
251 std::scoped_lock lock{sync_mutex}; 251 std::scoped_lock lock{sync_mutex};
252 u32 current_value = syncpoints.at(syncpoint_id).load();
253 if ((static_cast<s32>(current_value) - static_cast<s32>(value)) >= 0) {
254 TriggerCpuInterrupt(syncpoint_id, value);
255 return;
256 }
252 auto& interrupt = syncpt_interrupts.at(syncpoint_id); 257 auto& interrupt = syncpt_interrupts.at(syncpoint_id);
253 bool contains = std::any_of(interrupt.begin(), interrupt.end(), 258 bool contains = std::any_of(interrupt.begin(), interrupt.end(),
254 [value](u32 in_value) { return in_value == value; }); 259 [value](u32 in_value) { return in_value == value; });