mirror of
https://github.com/libretro/parallel-gx1.git
synced 2026-11-10 03:11:35 -10:00
A retro_run that draws nothing new allocates nothing; before, it made some thirty-six allocations: - Option lookups by key (IsUpdated and GetCached, about thirty a run) made a std::string of the key for an unordered_map. The options are now an array in the order of their definitions with an index sorted by key, searched with strcmp. - The JIT asks for its thread's stack bounds each time it starts running, every run with frame stepping, and glibc's pthread_getattr_np allocates. A thread's stack does not move: the bounds are kept per thread after the first time. - Every event pushed to the video thread, two a field for the XFB swap, was built with new. Events are now built in a ring of fixed slots: at most the queue's 1024 wait and one runs, so a slot comes round again only once its event is done. - A frame step, every run, posted a resume command to the real Wiimote manager, built with new. A momentary state change no longer resumes the remotes; a reported one still does.
68 lines
1.7 KiB
C++
68 lines
1.7 KiB
C++
// Copyright 2015 Dolphin Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#include "VideoCommon/AsyncRequests.h"
|
|
|
|
#include "Core/System.h"
|
|
#include "VideoCommon/Fifo.h"
|
|
#include "VideoCommon/VertexManagerBase.h"
|
|
|
|
AsyncRequests AsyncRequests::s_singleton;
|
|
|
|
AsyncRequests::AsyncRequests()
|
|
{
|
|
retro_waitable_spsc_init(&m_queue, QUEUE_REQUESTS * sizeof(Request*));
|
|
retro_eventcount_init(&m_completed);
|
|
}
|
|
|
|
AsyncRequests::~AsyncRequests()
|
|
{
|
|
retro_eventcount_free(&m_completed);
|
|
retro_waitable_spsc_free(&m_queue);
|
|
}
|
|
|
|
void AsyncRequests::PullEvents()
|
|
{
|
|
if (retro_spsc_read_avail(&m_queue.queue) < sizeof(Request*))
|
|
return;
|
|
|
|
// This is only called if the queue isn't empty.
|
|
// So just flush the pipeline to get accurate results.
|
|
g_vertex_manager->Flush();
|
|
|
|
Request* request;
|
|
while (retro_waitable_spsc_read(&m_queue, &request, sizeof(request)) == sizeof(request))
|
|
request->run(request);
|
|
}
|
|
|
|
void AsyncRequests::Submit(Request* request)
|
|
{
|
|
// Only waits when the video thread is QUEUE_REQUESTS requests behind.
|
|
while (!retro_waitable_spsc_wait_writable(&m_queue, sizeof(request), 1000000))
|
|
{
|
|
}
|
|
retro_waitable_spsc_write(&m_queue, &request, sizeof(request));
|
|
|
|
auto& system = Core::System::GetInstance();
|
|
system.GetFifo().RunGpu();
|
|
}
|
|
|
|
void AsyncRequests::WaitDone(retro_atomic_int_t* done)
|
|
{
|
|
while (!retro_atomic_load_acquire_int(done))
|
|
{
|
|
const int key = retro_eventcount_prepare_wait(&m_completed);
|
|
if (retro_atomic_load_acquire_int(done))
|
|
{
|
|
retro_eventcount_cancel_wait(&m_completed);
|
|
break;
|
|
}
|
|
retro_eventcount_commit_wait(&m_completed, key);
|
|
}
|
|
}
|
|
|
|
void AsyncRequests::SetPassthrough(bool enable)
|
|
{
|
|
m_passthrough = enable;
|
|
}
|