mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-10-31 16:09:03 -05:00 
			
		
		
		
	Merge pull request #2912 from FernandoS27/async-fixes
General fixes to Async GPU
This commit is contained in:
		| @@ -5,6 +5,7 @@ | ||||
| #include "common/assert.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "core/core.h" | ||||
| #include "core/core_timing.h" | ||||
| #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" | ||||
| #include "core/hle/service/nvdrv/devices/nvmap.h" | ||||
| #include "core/perf_stats.h" | ||||
| @@ -38,7 +39,10 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3 | ||||
|         transform, crop_rect}; | ||||
|  | ||||
|     system.GetPerfStats().EndGameFrame(); | ||||
|     system.GetPerfStats().EndSystemFrame(); | ||||
|     system.GPU().SwapBuffers(&framebuffer); | ||||
|     system.FrameLimiter().DoFrameLimiting(system.CoreTiming().GetGlobalTimeUs()); | ||||
|     system.GetPerfStats().BeginSystemFrame(); | ||||
| } | ||||
|  | ||||
| } // namespace Service::Nvidia::Devices | ||||
|   | ||||
| @@ -63,16 +63,26 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& | ||||
|         return NvResult::BadParameter; | ||||
|     } | ||||
|  | ||||
|     u32 event_id = params.value & 0x00FF; | ||||
|  | ||||
|     if (event_id >= MaxNvEvents) { | ||||
|         std::memcpy(output.data(), ¶ms, sizeof(params)); | ||||
|         return NvResult::BadParameter; | ||||
|     } | ||||
|  | ||||
|     auto event = events_interface.events[event_id]; | ||||
|     auto& gpu = system.GPU(); | ||||
|     // This is mostly to take into account unimplemented features. As synced | ||||
|     // gpu is always synced. | ||||
|     if (!gpu.IsAsync()) { | ||||
|         event.writable->Signal(); | ||||
|         return NvResult::Success; | ||||
|     } | ||||
|     auto lock = gpu.LockSync(); | ||||
|     const u32 current_syncpoint_value = gpu.GetSyncpointValue(params.syncpt_id); | ||||
|     const s32 diff = current_syncpoint_value - params.threshold; | ||||
|     if (diff >= 0) { | ||||
|         event.writable->Signal(); | ||||
|         params.value = current_syncpoint_value; | ||||
|         std::memcpy(output.data(), ¶ms, sizeof(params)); | ||||
|         return NvResult::Success; | ||||
| @@ -88,27 +98,6 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& | ||||
|         return NvResult::Timeout; | ||||
|     } | ||||
|  | ||||
|     u32 event_id; | ||||
|     if (is_async) { | ||||
|         event_id = params.value & 0x00FF; | ||||
|         if (event_id >= MaxNvEvents) { | ||||
|             std::memcpy(output.data(), ¶ms, sizeof(params)); | ||||
|             return NvResult::BadParameter; | ||||
|         } | ||||
|     } else { | ||||
|         if (ctrl.fresh_call) { | ||||
|             const auto result = events_interface.GetFreeEvent(); | ||||
|             if (result) { | ||||
|                 event_id = *result; | ||||
|             } else { | ||||
|                 LOG_CRITICAL(Service_NVDRV, "No Free Events available!"); | ||||
|                 event_id = params.value & 0x00FF; | ||||
|             } | ||||
|         } else { | ||||
|             event_id = ctrl.event_id; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     EventState status = events_interface.status[event_id]; | ||||
|     if (event_id < MaxNvEvents || status == EventState::Free || status == EventState::Registered) { | ||||
|         events_interface.SetEventStatus(event_id, EventState::Waiting); | ||||
| @@ -120,7 +109,7 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& | ||||
|             params.value = ((params.syncpt_id & 0xfff) << 16) | 0x10000000; | ||||
|         } | ||||
|         params.value |= event_id; | ||||
|         events_interface.events[event_id].writable->Clear(); | ||||
|         event.writable->Clear(); | ||||
|         gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value); | ||||
|         if (!is_async && ctrl.fresh_call) { | ||||
|             ctrl.must_delay = true; | ||||
|   | ||||
| @@ -134,7 +134,9 @@ void NVDRV::QueryEvent(Kernel::HLERequestContext& ctx) { | ||||
|     IPC::ResponseBuilder rb{ctx, 3, 1}; | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|     if (event_id < MaxNvEvents) { | ||||
|         rb.PushCopyObjects(nvdrv->GetEvent(event_id)); | ||||
|         auto event = nvdrv->GetEvent(event_id); | ||||
|         event->Clear(); | ||||
|         rb.PushCopyObjects(event); | ||||
|         rb.Push<u32>(NvResult::Success); | ||||
|     } else { | ||||
|         rb.Push<u32>(0); | ||||
|   | ||||
| @@ -40,8 +40,8 @@ Module::Module(Core::System& system) { | ||||
|     auto& kernel = system.Kernel(); | ||||
|     for (u32 i = 0; i < MaxNvEvents; i++) { | ||||
|         std::string event_label = fmt::format("NVDRV::NvEvent_{}", i); | ||||
|         events_interface.events[i] = Kernel::WritableEvent::CreateEventPair( | ||||
|             kernel, Kernel::ResetType::Automatic, event_label); | ||||
|         events_interface.events[i] = | ||||
|             Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual, event_label); | ||||
|         events_interface.status[i] = EventState::Free; | ||||
|         events_interface.registered[i] = false; | ||||
|     } | ||||
|   | ||||
| @@ -187,14 +187,18 @@ void NVFlinger::Compose() { | ||||
|         MicroProfileFlip(); | ||||
|  | ||||
|         if (!buffer) { | ||||
|             // There was no queued buffer to draw, render previous frame | ||||
|             system.GetPerfStats().EndGameFrame(); | ||||
|             system.GPU().SwapBuffers({}); | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         const auto& igbp_buffer = buffer->get().igbp_buffer; | ||||
|  | ||||
|         const auto& gpu = system.GPU(); | ||||
|         const auto& multi_fence = buffer->get().multi_fence; | ||||
|         for (u32 fence_id = 0; fence_id < multi_fence.num_fences; fence_id++) { | ||||
|             const auto& fence = multi_fence.fences[fence_id]; | ||||
|             gpu.WaitFence(fence.id, fence.value); | ||||
|         } | ||||
|  | ||||
|         // Now send the buffer to the GPU for drawing. | ||||
|         // TODO(Subv): Support more than just disp0. The display device selection is probably based | ||||
|         // on which display we're drawing (Default, Internal, External, etc) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 bunnei
					bunnei