Skip to content

Commit

Permalink
cellGem: Use atomic wait instead of wait_for
Browse files Browse the repository at this point in the history
  • Loading branch information
Megamouse committed Jan 8, 2025
1 parent 82977da commit 8720341
Showing 1 changed file with 75 additions and 20 deletions.
95 changes: 75 additions & 20 deletions rpcs3/Emu/Cell/Modules/cellGem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,37 @@ struct gem_config_data

u64 start_timestamp_us = 0;

atomic_t<u32> m_wake_up = 0;
atomic_t<u32> m_done = 0;

void wake_up()
{
m_wake_up.release(1);
m_wake_up.notify_one();
}

void done()
{
m_done.release(1);
m_done.notify_one();
}

void wait_for_result()
{
if (!m_done)
{
m_done.wait(0);
m_done = 0;
}
}

gem_config_data& operator=(thread_state)
{
wake_up();
done();
return *this;
}

// helper functions
bool is_controller_ready(u32 gem_num) const
{
Expand Down Expand Up @@ -847,24 +878,39 @@ void gem_config_data::operator()()

while (thread_ctrl::state() != thread_state::aborting && !Emu.IsStopped())
{
while (!video_conversion_in_progress && thread_ctrl::state() != thread_state::aborting && !Emu.IsStopped())
atomic_wait_timeout timeout = atomic_wait_timeout::inf;

if (state && !video_conversion_in_progress)
{
if (state)
{
const u64 now_us = get_system_time();
constexpr u64 update_timeout = 100000; // Update controllers at 10Hz
constexpr u64 update_timeout_us = 100'000; // Update controllers at 10Hz
const u64 now_us = get_system_time();
const u64 elapsed_us = now_us - last_update_us;

if (now_us - last_update_us >= update_timeout)
{
last_update_us = now_us;
if (elapsed_us < update_timeout_us)
{
timeout = atomic_wait_timeout{(update_timeout_us - elapsed_us) * 1000};
}
else
{
timeout = atomic_wait_timeout{update_timeout_us * 1000};
last_update_us = now_us;

std::scoped_lock lock(mtx);
update_connections();
update_calibration_status();
}
std::scoped_lock lock(mtx);
update_connections();
update_calibration_status();
}
}

thread_ctrl::wait_for(1000);
if (!m_wake_up)
{
m_wake_up.wait(0, timeout);
}

m_wake_up = 0;

if (!video_conversion_in_progress)
{
continue;
}

if (thread_ctrl::state() == thread_state::aborting || Emu.IsStopped())
Expand All @@ -881,6 +927,7 @@ void gem_config_data::operator()()
if (g_cfg.io.camera != camera_handler::qt)
{
video_conversion_in_progress = false;
done();
continue;
}

Expand All @@ -897,6 +944,7 @@ void gem_config_data::operator()()
}

video_conversion_in_progress = false;
done();
}
}

Expand All @@ -920,12 +968,18 @@ class gem_tracker
m_wake_up.notify_one();
}

void done()
{
m_done.release(1);
m_done.notify_one();
}

void wait_for_result()
{
if (!m_done)
{
m_done.wait(0);
m_done.release(0);
m_done = 0;
}
}

Expand Down Expand Up @@ -984,6 +1038,7 @@ class gem_tracker
gem_tracker& operator=(thread_state)
{
wake_up();
done();
return *this;
}

Expand Down Expand Up @@ -1093,8 +1148,7 @@ class gem_tracker
}

// Notify that we are finished with this frame
m_done.release(1);
m_done.notify_one();
done();

m_busy.release(false);
}
Expand Down Expand Up @@ -1762,10 +1816,7 @@ error_code cellGemConvertVideoFinish()
return CELL_GEM_ERROR_CONVERT_NOT_STARTED;
}

while (gem.video_conversion_in_progress && !Emu.IsStopped())
{
thread_ctrl::wait_for(100);
}
gem.wait_for_result();

return CELL_OK;
}
Expand Down Expand Up @@ -1799,7 +1850,9 @@ error_code cellGemConvertVideoStart(vm::cptr<void> video_frame)
const auto& shared_data = g_fxo->get<gem_camera_shared>();
gem.video_data_in.resize(shared_data.size);
std::memcpy(gem.video_data_in.data(), video_frame.get_ptr(), gem.video_data_in.size());

gem.video_conversion_in_progress = true;
gem.wake_up();

return CELL_OK;
}
Expand Down Expand Up @@ -2639,6 +2692,8 @@ error_code cellGemInit(ppu_thread& ppu, vm::cptr<CellGemAttribute> attribute)
// TODO: is this correct?
gem.start_timestamp_us = get_guest_system_time();

gem.wake_up();

return CELL_OK;
}

Expand Down

0 comments on commit 8720341

Please sign in to comment.