diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/nx2_gsv.h | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/src/core/hle/service/nx2_gsv.h b/src/core/hle/service/nx2_gsv.h index 4731b35364..290d82746d 100644 --- a/src/core/hle/service/nx2_gsv.h +++ b/src/core/hle/service/nx2_gsv.h @@ -2347,7 +2347,7 @@ public: {8, &INx2VideoSession::Flush, "Flush"}, {101, &INx2VideoSession::Configure, "Configure"}, {109, &INx2VideoSession::SubmitInput, "SubmitInputBuffer"}, - {115, &INx2VideoSession::Succeed, "Finalize"}, + {115, &INx2VideoSession::Finalize, "Finalize"}, {200, &INx2VideoSession::Succeed, "Initialize"}, {201, &INx2VideoSession::Succeed, "InitializeWithFlag"}, {202, &INx2VideoSession::Succeed, "InitializeWithFlagAndValue"}, @@ -2419,6 +2419,10 @@ private: if (Nx2FirstVideoCommand(GetServiceName(), ctx.GetCommand())) { LOG_INFO(Service, "{} TIPC {} {} (first use): words {:08x}", GetServiceName(), ctx.GetCommand(), what, fmt::join(std::span<const u32>{w, 12}, " ")); + } else if (static const bool trace = std::getenv("EDEN_NX2_VDEC_TRACE") != nullptr; trace) { + // EDEN_NX2_VDEC_TRACE=1: every video decoder call at Info level. + LOG_INFO(Service, "{} TIPC {} {}: [2]={:#x} [3]={:#x} [4]={:#x} [5]={:#x}", + GetServiceName(), ctx.GetCommand(), what, w[2], w[3], w[4], w[5]); } else { LOG_DEBUG(Service, "{} TIPC {} {}: [2]={:#x} [3]={:#x} [4]={:#x} [5]={:#x}", GetServiceName(), ctx.GetCommand(), what, w[2], w[3], w[4], w[5]); @@ -2538,7 +2542,12 @@ private: // once: its fence is the syncpoint's current value. Mario Kart World releases its // images after a movie ends and waits for the returned fences; a fence for a frame // that never comes hung the game on a black screen after its title movie. - if (release_fence && m_stream_ended && m_inputs.empty() && m_decoded.empty()) { + static const bool release_now = [] { + const char* value = std::getenv("EDEN_NX2_VDEC_EOS_RELEASE_NOW"); + return value != nullptr && value[0] != '0'; + }(); + if (release_now && release_fence && m_stream_ended && m_inputs.empty() && + m_decoded.empty()) { const u32 reached = static_cast<u32>( system.Host1x().GetSyncpointManager().GetGuestSyncpointValue(m_syncpoint)); m_sync_base = reached; @@ -2610,11 +2619,39 @@ private: m_flush = true; m_stream_ended = false; m_ready->room.store(true, std::memory_order_relaxed); + // Only Stop: Bananza flushes (8) after its movies end and treats every completed + // fence as a frame to acquire. + if (ctx.GetCommand() == 207) { + CompleteHandedFences(); + } } m_cv.notify_one(); TipcReplyWords(ctx, {}); } + void Finalize(HLERequestContext& ctx) { + Log(ctx, "finalize"); + { + std::scoped_lock lk{m_mutex}; + CompleteHandedFences(); + } + TipcReplyWords(ctx, {}); + } + + // Advances the decoder's syncpoint to the last value handed out (m_mutex held). + void CompleteHandedFences() { + if (m_syncpoint == NoSyncpoint) { + return; + } + auto& syncpoints = system.Host1x().GetSyncpointManager(); + const u32 target = m_sync_base + m_handed; + u32 current = static_cast<u32>(syncpoints.GetGuestSyncpointValue(m_syncpoint)); + while (static_cast<s32>(target - current) > 0) { + syncpoints.IncrementGuest(m_syncpoint); + ++current; + } + } + void GetOutputInfo(HLERequestContext& ctx) { Log(ctx, "output info"); std::optional<Output> output; |
