diff --git a/src/core/libraries/gnmdriver/gnmdriver.cpp b/src/core/libraries/gnmdriver/gnmdriver.cpp index b2c5b752..cf1778d1 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.cpp +++ b/src/core/libraries/gnmdriver/gnmdriver.cpp @@ -3,6 +3,7 @@ #include "common/assert.h" #include "common/config.h" +#include "common/debug.h" #include "common/logging/log.h" #include "common/path_util.h" #include "common/slot_vector.h" @@ -264,6 +265,7 @@ static_assert(CtxInitSequence400.size() == 0x61); // In case if `submitDone` is issued we need to block submissions until GPU idle static u32 submission_lock{}; +std::condition_variable cv_lock{}; static std::mutex m_submission{}; static u64 frames_submitted{}; // frame counter static bool send_init_packet{true}; // initialize HW state before first game's submit in a frame @@ -277,6 +279,18 @@ struct AscQueueInfo { static Common::SlotVector asc_queues{}; static constexpr VAddr tessellation_factors_ring_addr = 0xFF0000000ULL; +static void ResetSubmissionLock(Platform::InterruptId irq) { + std::unique_lock lock{m_submission}; + submission_lock = 0; + cv_lock.notify_all(); +} + +static void WaitGpuIdle() { + HLE_TRACE; + std::unique_lock lock{m_submission}; + cv_lock.wait(lock, [] { return submission_lock == 0; }); +} + static void DumpCommandList(std::span cmd_list, const std::string& postfix) { using namespace Common::FS; const auto dump_dir = GetUserPath(PathType::PM4Dir); @@ -465,14 +479,9 @@ void PS4_SYSV_ABI sceGnmDingDong(u32 gnm_vqid, u32 next_offs_dw) { return; } - std::unique_lock lock{m_submission}; - if (submission_lock != 0) { - liverpool->WaitGpuIdle(); + WaitGpuIdle(); - // Suspend logic goes here - - submission_lock = 0; - } + /* Suspend logic goes here */ auto vqid = gnm_vqid - 1; auto& asc_queue = asc_queues[{vqid}]; @@ -1930,13 +1939,9 @@ s32 PS4_SYSV_ABI sceGnmSubmitCommandBuffers(u32 count, const u32* dcb_gpu_addrs[ } } - if (submission_lock != 0) { - liverpool->WaitGpuIdle(); + WaitGpuIdle(); - // Suspend logic goes here - - submission_lock = 0; - } + /* Suspend logic goes here */ if (send_init_packet) { if (sdk_version <= 0x1ffffffu) { @@ -1990,7 +1995,6 @@ int PS4_SYSV_ABI sceGnmSubmitDone() { if (!liverpool->IsGpuIdle()) { submission_lock = true; } - liverpool->NotifySubmitDone(); send_init_packet = true; ++frames_submitted; return ORBIS_OK; @@ -2471,6 +2475,9 @@ void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym) { sdk_version = 0; } + Platform::IrqC::Instance()->Register(Platform::InterruptId::GpuIdle, ResetSubmissionLock, + nullptr); + LIB_FUNCTION("b0xyllnVY-I", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmAddEqEvent); LIB_FUNCTION("b08AgtPlHPg", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmAreSubmitsAllowed); diff --git a/src/core/platform.h b/src/core/platform.h index d8064c52..2c38dfd3 100644 --- a/src/core/platform.h +++ b/src/core/platform.h @@ -26,6 +26,7 @@ enum class InterruptId : u32 { Compute6RelMem = 6u, GfxEop = 7u, GfxFlip = 8u, + GpuIdle = 9u, }; using IrqHandler = std::function; diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp index 2c3590fe..4bc73c67 100644 --- a/src/video_core/amdgpu/liverpool.cpp +++ b/src/video_core/amdgpu/liverpool.cpp @@ -66,21 +66,10 @@ void Liverpool::Process(std::stop_token stoken) { } } - if (submit_done) { - std::scoped_lock lk{submit_mutex}; - submit_cv.notify_all(); - submit_done = false; - } + Platform::IrqC::Instance()->Signal(Platform::InterruptId::GpuIdle); } } -void Liverpool::WaitGpuIdle() { - RENDERER_TRACE; - - std::unique_lock lk{submit_mutex}; - submit_cv.wait(lk, [this] { return num_submits == 0; }); -} - Liverpool::Task Liverpool::ProcessCeUpdate(std::span ccb) { TracyFiberEnter(ccb_task_name); diff --git a/src/video_core/amdgpu/liverpool.h b/src/video_core/amdgpu/liverpool.h index d18482f6..e12c626d 100644 --- a/src/video_core/amdgpu/liverpool.h +++ b/src/video_core/amdgpu/liverpool.h @@ -937,18 +937,10 @@ public: void SubmitGfx(std::span dcb, std::span ccb); void SubmitAsc(u32 vqid, std::span acb); - void WaitGpuIdle(); - bool IsGpuIdle() const { return num_submits == 0; } - void NotifySubmitDone() { - std::scoped_lock lk{submit_mutex}; - submit_done = true; - submit_cv.notify_all(); - } - void BindRasterizer(Vulkan::Rasterizer* rasterizer_) { rasterizer = rasterizer_; } @@ -1017,7 +1009,6 @@ private: u32 num_submits{}; std::mutex submit_mutex; std::condition_variable_any submit_cv; - std::atomic submit_done{}; }; static_assert(GFX6_3D_REG_INDEX(ps_program) == 0x2C08);