mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-10-11 22:49:55 +00:00
cellVdec: Postpone Context Destruction
This commit is contained in:
@@ -298,9 +298,15 @@ struct vdec_context final
|
||||
}
|
||||
|
||||
~vdec_context()
|
||||
{
|
||||
release_decoder();
|
||||
}
|
||||
|
||||
// Frees the FFmpeg decoder, which may take milliseconds
|
||||
void release_decoder()
|
||||
{
|
||||
avcodec_free_context(&ctx);
|
||||
sws_freeContext(sws);
|
||||
sws_freeContext(std::exchange(sws, nullptr));
|
||||
}
|
||||
|
||||
static u32 freq_to_framerate_code(f64 freq)
|
||||
@@ -653,6 +659,38 @@ struct vdec_context final
|
||||
}
|
||||
};
|
||||
|
||||
// Frees the FFmpeg decoders of closed contexts on a host thread.
|
||||
// Freeing a decoder takes milliseconds, which would otherwise delay the guest thread closing it.
|
||||
struct vdec_context_reaper
|
||||
{
|
||||
lf_queue<shared_ptr<vdec_context>> contexts;
|
||||
|
||||
void operator()()
|
||||
{
|
||||
while (thread_ctrl::state() != thread_state::aborting)
|
||||
{
|
||||
thread_ctrl::wait_on(contexts);
|
||||
|
||||
// Let the closing sequence of the caller complete first: freeing this much memory slows down the other threads
|
||||
thread_ctrl::wait_for(100'000);
|
||||
|
||||
for (auto&& vdec : contexts.pop_all())
|
||||
{
|
||||
if (vdec.use_count() > 1)
|
||||
{
|
||||
// Still used by an HLE call in progress, retry later
|
||||
contexts.push(std::move(vdec));
|
||||
continue;
|
||||
}
|
||||
|
||||
vdec->release_decoder();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr auto thread_name = "HLE Video Decoder Reaper"sv;
|
||||
};
|
||||
|
||||
extern bool check_if_vdec_contexts_exist()
|
||||
{
|
||||
bool context_exists = false;
|
||||
@@ -1493,12 +1531,15 @@ error_code cellVdecClose(ppu_thread& ppu, u32 handle)
|
||||
vdec->seq_state = sequence_state::closed;
|
||||
vdec->mutex.lock_unlock();
|
||||
|
||||
if (!idm::remove_verify<vdec_context>(handle, std::move(vdec)))
|
||||
if (!idm::remove_verify<vdec_context>(handle, vdec))
|
||||
{
|
||||
// Other thread removed it beforehead
|
||||
return { CELL_VDEC_ERROR_ARG, "remove_verify failed" };
|
||||
}
|
||||
|
||||
// Let the reaper free the decoder so that the caller does not pay for it
|
||||
g_fxo->get<named_thread<vdec_context_reaper>>().contexts.push(std::move(vdec));
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user