Skip to content

Commit

Permalink
Add an experimental threaded RDP setting
Browse files Browse the repository at this point in the history
  • Loading branch information
Hydr8gon committed May 9, 2023
1 parent 62999da commit 8040271
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 5 deletions.
1 change: 1 addition & 0 deletions src/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ void Core::stop()
saveThread->join();
delete emuThread;
delete saveThread;
RDP::finishThread();
}
}

Expand Down
11 changes: 11 additions & 0 deletions src/desktop/ry_frame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ enum FrameEvent
STOP,
INPUT_BINDINGS,
FPS_LIMITER,
THREADED_RDP,
TEX_FILTER,
UPDATE_JOY
};
Expand All @@ -48,6 +49,7 @@ EVT_MENU(RESTART, ryFrame::restart)
EVT_MENU(STOP, ryFrame::stop)
EVT_MENU(INPUT_BINDINGS, ryFrame::inputSettings)
EVT_MENU(FPS_LIMITER, ryFrame::toggleFpsLimit)
EVT_MENU(THREADED_RDP, ryFrame::toggleThreadRdp)
EVT_MENU(TEX_FILTER, ryFrame::toggleTexFilter)
EVT_TIMER(UPDATE_JOY, ryFrame::updateJoystick)
EVT_DROP_FILES(ryFrame::dropFiles)
Expand Down Expand Up @@ -75,10 +77,12 @@ ryFrame::ryFrame(std::string path): wxFrame(nullptr, wxID_ANY, "rokuyon")
settingsMenu->Append(INPUT_BINDINGS, "&Input Bindings");
settingsMenu->AppendSeparator();
settingsMenu->AppendCheckItem(FPS_LIMITER, "&FPS Limiter");
settingsMenu->AppendCheckItem(THREADED_RDP, "&Threaded RDP");
settingsMenu->AppendCheckItem(TEX_FILTER, "&Texture Filter");

// Set the initial checkbox states
settingsMenu->Check(FPS_LIMITER, Settings::fpsLimiter);
settingsMenu->Check(THREADED_RDP, Settings::threadedRdp);
settingsMenu->Check(TEX_FILTER, Settings::texFilter);

// Set up the menu bar
Expand Down Expand Up @@ -313,6 +317,13 @@ void ryFrame::toggleFpsLimit(wxCommandEvent &event)
Settings::save();
}

void ryFrame::toggleThreadRdp(wxCommandEvent &event)
{
// Toggle the threaded RDP setting
Settings::threadedRdp = !Settings::threadedRdp;
Settings::save();
}

void ryFrame::toggleTexFilter(wxCommandEvent &event)
{
// Toggle the texture filter setting
Expand Down
1 change: 1 addition & 0 deletions src/desktop/ry_frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class ryFrame: public wxFrame
void stop(wxCommandEvent &event);
void inputSettings(wxCommandEvent &event);
void toggleFpsLimit(wxCommandEvent &event);
void toggleThreadRdp(wxCommandEvent &event);
void toggleTexFilter(wxCommandEvent &event);
void updateJoystick(wxTimerEvent &event);
void dropFiles(wxDropFilesEvent &event);
Expand Down
78 changes: 74 additions & 4 deletions src/rdp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@

#include <algorithm>
#include <cstring>
#include <mutex>
#include <thread>
#include <vector>

#include "rdp.h"
#include "log.h"
Expand Down Expand Up @@ -63,6 +66,10 @@ namespace RDP
extern void (*commands[])();
extern uint8_t paramCounts[];

std::thread *thread;
std::mutex mutex;
bool running;

uint8_t tmem[0x1000]; // 4KB TMEM
uint32_t startAddr;
uint32_t endAddr;
Expand All @@ -71,7 +78,7 @@ namespace RDP
uint32_t addrBase;
uint32_t addrMask;
uint8_t paramCount;
uint64_t opcode[22];
std::vector<uint64_t> opcode;

CycleType cycleType;
bool texFilter;
Expand Down Expand Up @@ -130,7 +137,9 @@ namespace RDP
bool blendPixel(bool cycle, uint32_t &color);
bool drawPixel(int x, int y);

void runThreaded();
void runCommands();

void triangle();
void triDepth();
void triTexture();
Expand Down Expand Up @@ -204,6 +213,7 @@ void RDP::reset()
addrBase = 0xA0000000;
addrMask = 0x3FFFFF;
paramCount = 0;
opcode.clear();
cycleType = ONE_CYCLE;
texFilter = false;
blendA[0] = blendA[1] = 0;
Expand Down Expand Up @@ -664,24 +674,84 @@ bool RDP::drawPixel(int x, int y)
return false;
}

void RDP::finishThread()
{
// Stop the thread if it was running
if (running)
{
running = false;
thread->join();
delete thread;
}
}

void RDP::runThreaded()
{
while (true)
{
// Parse the next command if one is queued
mutex.lock();
uint8_t op = opcode.empty() ? 0 : ((opcode[0] >> 56) & 0x3F);
uint8_t count = paramCounts[op];

if (opcode.size() >= count)
{
// Execute a command once all of its parameters have been queued
mutex.unlock();
(*commands[op])();
mutex.lock();
opcode.erase(opcode.begin(), opcode.begin() + count);
mutex.unlock();
}
else
{
// If requested, stop running when the queue is empty
mutex.unlock();
if (!running) return;
std::this_thread::yield();
}
}
}

void RDP::runCommands()
{
// Start the thread if enabled and not running
if (Settings::threadedRdp && !running)
{
running = true;
thread = new std::thread(runThreaded);
}

mutex.lock();

// Process RDP commands until the end address is reached
while (startAddr < endAddr)
{
// Add a parameter to the buffer
opcode[paramCount++] = Memory::read<uint64_t>(addrBase + (startAddr & addrMask));
opcode.push_back(Memory::read<uint64_t>(addrBase + (startAddr & addrMask)));
paramCount++;

// Execute a command once all of its parameters have been received
if (paramCount >= paramCounts[(opcode[0] >> 56) & 0x3F])
// When threaded, only run sync commands here; the rest will run on the thread
uint8_t op = (opcode[opcode.size() - paramCount] >> 56) & 0x3F;
if (paramCount >= paramCounts[op])
{
(*commands[(opcode[0] >> 56) & 0x3F])();
paramCount = 0;
if (!running || op == 0x29) // Sync Full
{
mutex.unlock();
finishThread();
mutex.lock();
(*commands[op])();
opcode.clear();
}
}

// Move to the next parameter
startAddr += 8;
}

mutex.unlock();
}

void RDP::triangle()
Expand Down
1 change: 1 addition & 0 deletions src/rdp.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ namespace RDP
void reset();
uint32_t read(int index);
void write(int index, uint32_t value);
void finishThread();
}

#endif // RDP_H
2 changes: 2 additions & 0 deletions src/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@ namespace Settings
{
std::string filename;
int fpsLimiter = 1;
int threadedRdp = 0;
int texFilter = 1;

std::vector<Setting> settings =
{
Setting("fpsLimiter", &fpsLimiter, false),
Setting("threadedRdp", &threadedRdp, false),
Setting("texFilter", &texFilter, false)
};
}
Expand Down
1 change: 1 addition & 0 deletions src/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ namespace Settings
bool save();

extern int fpsLimiter;
extern int threadedRdp;
extern int texFilter;
}

Expand Down
4 changes: 3 additions & 1 deletion src/switch/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ void settingsMenu()
std::vector<ListItem> settings =
{
ListItem("FPS Limiter", toggle[Settings::fpsLimiter]),
ListItem("Threaded RDP", toggle[Settings::threadedRdp]),
ListItem("Texture Filter", toggle[Settings::texFilter])
};

Expand All @@ -119,7 +120,8 @@ void settingsMenu()
switch (index)
{
case 0: Settings::fpsLimiter = !Settings::fpsLimiter; break;
case 1: Settings::texFilter = !Settings::texFilter; break;
case 1: Settings::threadedRdp = !Settings::threadedRdp; break;
case 2: Settings::texFilter = !Settings::texFilter; break;
}
}
else
Expand Down
4 changes: 4 additions & 0 deletions src/vi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "log.h"
#include "memory.h"
#include "mi.h"
#include "rdp.h"

namespace VI
{
Expand Down Expand Up @@ -151,6 +152,9 @@ void VI::write(uint32_t address, uint32_t value)

void VI::drawFrame()
{
// Ensure the RDP thread has finished drawing
RDP::finishThread();

// Allow up to 2 framebuffers to be queued, to preserve frame pacing if emulation runs ahead
if (framebuffers.size() < 2)
{
Expand Down

0 comments on commit 8040271

Please sign in to comment.