summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/core.cpp2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp4
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp33
-rw-r--r--src/core/hle/service/nvdrv/interface.cpp4
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.cpp4
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp10
6 files changed, 29 insertions, 28 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 4d0ac72a5..ddc767e30 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -256,6 +256,8 @@ struct System::Impl {
256 is_powered_on = false; 256 is_powered_on = false;
257 exit_lock = false; 257 exit_lock = false;
258 258
259 gpu_core->WaitIdle();
260
259 // Shutdown emulation session 261 // Shutdown emulation session
260 renderer.reset(); 262 renderer.reset();
261 GDBStub::Shutdown(); 263 GDBStub::Shutdown();
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
index f764388bc..3f7b8e670 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
@@ -5,6 +5,7 @@
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7#include "core/core.h" 7#include "core/core.h"
8#include "core/core_timing.h"
8#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" 9#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
9#include "core/hle/service/nvdrv/devices/nvmap.h" 10#include "core/hle/service/nvdrv/devices/nvmap.h"
10#include "core/perf_stats.h" 11#include "core/perf_stats.h"
@@ -38,7 +39,10 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3
38 transform, crop_rect}; 39 transform, crop_rect};
39 40
40 system.GetPerfStats().EndGameFrame(); 41 system.GetPerfStats().EndGameFrame();
42 system.GetPerfStats().EndSystemFrame();
41 system.GPU().SwapBuffers(&framebuffer); 43 system.GPU().SwapBuffers(&framebuffer);
44 system.FrameLimiter().DoFrameLimiting(system.CoreTiming().GetGlobalTimeUs());
45 system.GetPerfStats().BeginSystemFrame();
42} 46}
43 47
44} // namespace Service::Nvidia::Devices 48} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
index eb88fee1b..b27ee0502 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
@@ -63,16 +63,26 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>&
63 return NvResult::BadParameter; 63 return NvResult::BadParameter;
64 } 64 }
65 65
66 u32 event_id = params.value & 0x00FF;
67
68 if (event_id >= MaxNvEvents) {
69 std::memcpy(output.data(), &params, sizeof(params));
70 return NvResult::BadParameter;
71 }
72
73 auto event = events_interface.events[event_id];
66 auto& gpu = system.GPU(); 74 auto& gpu = system.GPU();
67 // This is mostly to take into account unimplemented features. As synced 75 // This is mostly to take into account unimplemented features. As synced
68 // gpu is always synced. 76 // gpu is always synced.
69 if (!gpu.IsAsync()) { 77 if (!gpu.IsAsync()) {
78 event.writable->Signal();
70 return NvResult::Success; 79 return NvResult::Success;
71 } 80 }
72 auto lock = gpu.LockSync(); 81 auto lock = gpu.LockSync();
73 const u32 current_syncpoint_value = gpu.GetSyncpointValue(params.syncpt_id); 82 const u32 current_syncpoint_value = gpu.GetSyncpointValue(params.syncpt_id);
74 const s32 diff = current_syncpoint_value - params.threshold; 83 const s32 diff = current_syncpoint_value - params.threshold;
75 if (diff >= 0) { 84 if (diff >= 0) {
85 event.writable->Signal();
76 params.value = current_syncpoint_value; 86 params.value = current_syncpoint_value;
77 std::memcpy(output.data(), &params, sizeof(params)); 87 std::memcpy(output.data(), &params, sizeof(params));
78 return NvResult::Success; 88 return NvResult::Success;
@@ -88,27 +98,6 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>&
88 return NvResult::Timeout; 98 return NvResult::Timeout;
89 } 99 }
90 100
91 u32 event_id;
92 if (is_async) {
93 event_id = params.value & 0x00FF;
94 if (event_id >= MaxNvEvents) {
95 std::memcpy(output.data(), &params, sizeof(params));
96 return NvResult::BadParameter;
97 }
98 } else {
99 if (ctrl.fresh_call) {
100 const auto result = events_interface.GetFreeEvent();
101 if (result) {
102 event_id = *result;
103 } else {
104 LOG_CRITICAL(Service_NVDRV, "No Free Events available!");
105 event_id = params.value & 0x00FF;
106 }
107 } else {
108 event_id = ctrl.event_id;
109 }
110 }
111
112 EventState status = events_interface.status[event_id]; 101 EventState status = events_interface.status[event_id];
113 if (event_id < MaxNvEvents || status == EventState::Free || status == EventState::Registered) { 102 if (event_id < MaxNvEvents || status == EventState::Free || status == EventState::Registered) {
114 events_interface.SetEventStatus(event_id, EventState::Waiting); 103 events_interface.SetEventStatus(event_id, EventState::Waiting);
@@ -120,7 +109,7 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>&
120 params.value = ((params.syncpt_id & 0xfff) << 16) | 0x10000000; 109 params.value = ((params.syncpt_id & 0xfff) << 16) | 0x10000000;
121 } 110 }
122 params.value |= event_id; 111 params.value |= event_id;
123 events_interface.events[event_id].writable->Clear(); 112 event.writable->Clear();
124 gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value); 113 gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value);
125 if (!is_async && ctrl.fresh_call) { 114 if (!is_async && ctrl.fresh_call) {
126 ctrl.must_delay = true; 115 ctrl.must_delay = true;
diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp
index 5e0c23602..68d139cfb 100644
--- a/src/core/hle/service/nvdrv/interface.cpp
+++ b/src/core/hle/service/nvdrv/interface.cpp
@@ -134,7 +134,9 @@ void NVDRV::QueryEvent(Kernel::HLERequestContext& ctx) {
134 IPC::ResponseBuilder rb{ctx, 3, 1}; 134 IPC::ResponseBuilder rb{ctx, 3, 1};
135 rb.Push(RESULT_SUCCESS); 135 rb.Push(RESULT_SUCCESS);
136 if (event_id < MaxNvEvents) { 136 if (event_id < MaxNvEvents) {
137 rb.PushCopyObjects(nvdrv->GetEvent(event_id)); 137 auto event = nvdrv->GetEvent(event_id);
138 event->Clear();
139 rb.PushCopyObjects(event);
138 rb.Push<u32>(NvResult::Success); 140 rb.Push<u32>(NvResult::Success);
139 } else { 141 } else {
140 rb.Push<u32>(0); 142 rb.Push<u32>(0);
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp
index 307a7e928..7bfb99e34 100644
--- a/src/core/hle/service/nvdrv/nvdrv.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv.cpp
@@ -40,8 +40,8 @@ Module::Module(Core::System& system) {
40 auto& kernel = system.Kernel(); 40 auto& kernel = system.Kernel();
41 for (u32 i = 0; i < MaxNvEvents; i++) { 41 for (u32 i = 0; i < MaxNvEvents; i++) {
42 std::string event_label = fmt::format("NVDRV::NvEvent_{}", i); 42 std::string event_label = fmt::format("NVDRV::NvEvent_{}", i);
43 events_interface.events[i] = Kernel::WritableEvent::CreateEventPair( 43 events_interface.events[i] =
44 kernel, Kernel::ResetType::Automatic, event_label); 44 Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual, event_label);
45 events_interface.status[i] = EventState::Free; 45 events_interface.status[i] = EventState::Free;
46 events_interface.registered[i] = false; 46 events_interface.registered[i] = false;
47 } 47 }
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index 368f83f6c..cc9522aad 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -187,14 +187,18 @@ void NVFlinger::Compose() {
187 MicroProfileFlip(); 187 MicroProfileFlip();
188 188
189 if (!buffer) { 189 if (!buffer) {
190 // There was no queued buffer to draw, render previous frame
191 system.GetPerfStats().EndGameFrame();
192 system.GPU().SwapBuffers({});
193 continue; 190 continue;
194 } 191 }
195 192
196 const auto& igbp_buffer = buffer->get().igbp_buffer; 193 const auto& igbp_buffer = buffer->get().igbp_buffer;
197 194
195 const auto& gpu = system.GPU();
196 const auto& multi_fence = buffer->get().multi_fence;
197 for (u32 fence_id = 0; fence_id < multi_fence.num_fences; fence_id++) {
198 const auto& fence = multi_fence.fences[fence_id];
199 gpu.WaitFence(fence.id, fence.value);
200 }
201
198 // Now send the buffer to the GPU for drawing. 202 // Now send the buffer to the GPU for drawing.
199 // TODO(Subv): Support more than just disp0. The display device selection is probably based 203 // TODO(Subv): Support more than just disp0. The display device selection is probably based
200 // on which display we're drawing (Default, Internal, External, etc) 204 // on which display we're drawing (Default, Internal, External, etc)