mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-01 10:31:31 +02:00
VideoCommon: fifo cleanups
This commit is contained in:
parent
27f984c02e
commit
4b22885ed8
@ -41,10 +41,10 @@ bool g_use_deterministic_gpu_thread;
|
||||
static std::mutex s_video_buffer_lock;
|
||||
static std::condition_variable s_video_buffer_cond;
|
||||
static u8* s_video_buffer;
|
||||
u8* g_video_buffer_read_ptr;
|
||||
static u8* s_video_buffer_read_ptr;
|
||||
static std::atomic<u8*> s_video_buffer_write_ptr;
|
||||
static std::atomic<u8*> s_video_buffer_seen_ptr;
|
||||
u8* g_video_buffer_pp_read_ptr;
|
||||
static u8* s_video_buffer_pp_read_ptr;
|
||||
// The read_ptr is always owned by the GPU thread. In normal mode, so is the
|
||||
// write_ptr, despite it being atomic. In g_use_deterministic_gpu_thread mode,
|
||||
// things get a bit more complicated:
|
||||
@ -63,11 +63,11 @@ void Fifo_DoState(PointerWrap &p)
|
||||
u8* write_ptr = s_video_buffer_write_ptr;
|
||||
p.DoPointer(write_ptr, s_video_buffer);
|
||||
s_video_buffer_write_ptr = write_ptr;
|
||||
p.DoPointer(g_video_buffer_read_ptr, s_video_buffer);
|
||||
p.DoPointer(s_video_buffer_read_ptr, s_video_buffer);
|
||||
if (p.mode == PointerWrap::MODE_READ && g_use_deterministic_gpu_thread)
|
||||
{
|
||||
// We're good and paused, right?
|
||||
s_video_buffer_seen_ptr = g_video_buffer_pp_read_ptr = g_video_buffer_read_ptr;
|
||||
s_video_buffer_seen_ptr = s_video_buffer_pp_read_ptr = s_video_buffer_read_ptr;
|
||||
}
|
||||
p.Do(g_bSkipCurrentFrame);
|
||||
}
|
||||
@ -106,8 +106,8 @@ void Fifo_Shutdown()
|
||||
FreeMemoryPages(s_video_buffer, FIFO_SIZE);
|
||||
s_video_buffer = nullptr;
|
||||
s_video_buffer_write_ptr = nullptr;
|
||||
g_video_buffer_pp_read_ptr = nullptr;
|
||||
g_video_buffer_read_ptr = nullptr;
|
||||
s_video_buffer_pp_read_ptr = nullptr;
|
||||
s_video_buffer_read_ptr = nullptr;
|
||||
s_video_buffer_seen_ptr = nullptr;
|
||||
s_fifo_aux_write_ptr = nullptr;
|
||||
s_fifo_aux_read_ptr = nullptr;
|
||||
@ -169,15 +169,15 @@ void SyncGPU(SyncGPUReason reason, bool may_move_read_ptr)
|
||||
if (may_move_read_ptr)
|
||||
{
|
||||
// what's left over in the buffer
|
||||
size_t size = write_ptr - g_video_buffer_pp_read_ptr;
|
||||
size_t size = write_ptr - s_video_buffer_pp_read_ptr;
|
||||
|
||||
memmove(s_video_buffer, g_video_buffer_pp_read_ptr, size);
|
||||
memmove(s_video_buffer, s_video_buffer_pp_read_ptr, size);
|
||||
// This change always decreases the pointers. We write seen_ptr
|
||||
// after write_ptr here, and read it before in RunGpuLoop, so
|
||||
// 'write_ptr > seen_ptr' there cannot become spuriously true.
|
||||
s_video_buffer_write_ptr = write_ptr = s_video_buffer + size;
|
||||
g_video_buffer_pp_read_ptr = s_video_buffer;
|
||||
g_video_buffer_read_ptr = s_video_buffer;
|
||||
s_video_buffer_pp_read_ptr = s_video_buffer;
|
||||
s_video_buffer_read_ptr = s_video_buffer;
|
||||
s_video_buffer_seen_ptr = write_ptr;
|
||||
}
|
||||
}
|
||||
@ -213,15 +213,15 @@ static void ReadDataFromFifo(u32 readPtr)
|
||||
size_t len = 32;
|
||||
if (len > (size_t)(s_video_buffer + FIFO_SIZE - s_video_buffer_write_ptr))
|
||||
{
|
||||
size_t existing_len = s_video_buffer_write_ptr - g_video_buffer_read_ptr;
|
||||
size_t existing_len = s_video_buffer_write_ptr - s_video_buffer_read_ptr;
|
||||
if (len > (size_t)(FIFO_SIZE - existing_len))
|
||||
{
|
||||
PanicAlert("FIFO out of bounds (existing %lu + new %lu > %lu)", (unsigned long) existing_len, (unsigned long) len, (unsigned long) FIFO_SIZE);
|
||||
return;
|
||||
}
|
||||
memmove(s_video_buffer, g_video_buffer_read_ptr, existing_len);
|
||||
memmove(s_video_buffer, s_video_buffer_read_ptr, existing_len);
|
||||
s_video_buffer_write_ptr = s_video_buffer + existing_len;
|
||||
g_video_buffer_read_ptr = s_video_buffer;
|
||||
s_video_buffer_read_ptr = s_video_buffer;
|
||||
}
|
||||
// Copy new video instructions to s_video_buffer for future use in rendering the new picture
|
||||
Memory::CopyFromEmu(s_video_buffer_write_ptr, readPtr, len);
|
||||
@ -238,13 +238,13 @@ static void ReadDataFromFifoOnCPU(u32 readPtr)
|
||||
// We can't wrap around while the GPU is working on the data.
|
||||
// This should be very rare due to the reset in SyncGPU.
|
||||
SyncGPU(SYNC_GPU_WRAPAROUND);
|
||||
if (g_video_buffer_pp_read_ptr != g_video_buffer_read_ptr)
|
||||
if (s_video_buffer_pp_read_ptr != s_video_buffer_read_ptr)
|
||||
{
|
||||
PanicAlert("desynced read pointers");
|
||||
return;
|
||||
}
|
||||
write_ptr = s_video_buffer_write_ptr;
|
||||
size_t existing_len = write_ptr - g_video_buffer_pp_read_ptr;
|
||||
size_t existing_len = write_ptr - s_video_buffer_pp_read_ptr;
|
||||
if (len > (size_t)(FIFO_SIZE - existing_len))
|
||||
{
|
||||
PanicAlert("FIFO out of bounds (existing %lu + new %lu > %lu)", (unsigned long) existing_len, (unsigned long) len, (unsigned long) FIFO_SIZE);
|
||||
@ -252,17 +252,17 @@ static void ReadDataFromFifoOnCPU(u32 readPtr)
|
||||
}
|
||||
}
|
||||
Memory::CopyFromEmu(s_video_buffer_write_ptr, readPtr, len);
|
||||
OpcodeDecoder_Preprocess(write_ptr + len, false);
|
||||
s_video_buffer_pp_read_ptr = OpcodeDecoder_Preprocess(s_video_buffer_pp_read_ptr, write_ptr + len, false);
|
||||
// This would have to be locked if the GPU thread didn't spin.
|
||||
s_video_buffer_write_ptr = write_ptr + len;
|
||||
}
|
||||
|
||||
void ResetVideoBuffer()
|
||||
{
|
||||
g_video_buffer_read_ptr = s_video_buffer;
|
||||
s_video_buffer_read_ptr = s_video_buffer;
|
||||
s_video_buffer_write_ptr = s_video_buffer;
|
||||
s_video_buffer_seen_ptr = s_video_buffer;
|
||||
g_video_buffer_pp_read_ptr = s_video_buffer;
|
||||
s_video_buffer_pp_read_ptr = s_video_buffer;
|
||||
s_fifo_aux_write_ptr = s_fifo_aux_data;
|
||||
s_fifo_aux_read_ptr = s_fifo_aux_data;
|
||||
}
|
||||
@ -294,7 +294,7 @@ void RunGpuLoop()
|
||||
// See comment in SyncGPU
|
||||
if (write_ptr > seen_ptr)
|
||||
{
|
||||
OpcodeDecoder_Run(write_ptr, false);
|
||||
s_video_buffer_read_ptr = OpcodeDecoder_Run(s_video_buffer_read_ptr, write_ptr, nullptr, false);
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> vblk(s_video_buffer_lock);
|
||||
@ -330,7 +330,7 @@ void RunGpuLoop()
|
||||
|
||||
|
||||
u8* write_ptr = s_video_buffer_write_ptr;
|
||||
cyclesExecuted = OpcodeDecoder_Run(write_ptr, false);
|
||||
s_video_buffer_read_ptr = OpcodeDecoder_Run(s_video_buffer_read_ptr, write_ptr, &cyclesExecuted, false);
|
||||
|
||||
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSyncGPU && Common::AtomicLoad(CommandProcessor::VITicks) >= cyclesExecuted)
|
||||
@ -338,7 +338,7 @@ void RunGpuLoop()
|
||||
|
||||
Common::AtomicStore(fifo.CPReadPointer, readPtr);
|
||||
Common::AtomicAdd(fifo.CPReadWriteDistance, -32);
|
||||
if ((write_ptr - g_video_buffer_read_ptr) == 0)
|
||||
if ((write_ptr - s_video_buffer_read_ptr) == 0)
|
||||
Common::AtomicStore(fifo.SafeCPReadPointer, fifo.CPReadPointer);
|
||||
}
|
||||
|
||||
@ -403,7 +403,7 @@ void RunGpu()
|
||||
FPURoundMode::SaveSIMDState();
|
||||
FPURoundMode::LoadDefaultSIMDState();
|
||||
ReadDataFromFifo(fifo.CPReadPointer);
|
||||
OpcodeDecoder_Run(s_video_buffer_write_ptr, false);
|
||||
s_video_buffer_read_ptr = OpcodeDecoder_Run(s_video_buffer_read_ptr, s_video_buffer_write_ptr, nullptr, false);
|
||||
FPURoundMode::LoadSIMDState();
|
||||
}
|
||||
|
||||
@ -454,7 +454,7 @@ void Fifo_UpdateWantDeterminism(bool want)
|
||||
if (gpu_thread)
|
||||
{
|
||||
// These haven't been updated in non-deterministic mode.
|
||||
s_video_buffer_seen_ptr = g_video_buffer_pp_read_ptr = g_video_buffer_read_ptr;
|
||||
s_video_buffer_seen_ptr = s_video_buffer_pp_read_ptr = s_video_buffer_read_ptr;
|
||||
CopyPreprocessCPStateFromMain();
|
||||
VertexLoaderManager::MarkAllDirty();
|
||||
}
|
||||
|
@ -17,7 +17,6 @@ extern bool g_bSkipCurrentFrame;
|
||||
// and can change at runtime.
|
||||
extern bool g_use_deterministic_gpu_thread;
|
||||
extern std::atomic<u8*> g_video_buffer_write_ptr_xthread;
|
||||
extern u8* g_video_buffer_pp_read_ptr;
|
||||
|
||||
void Fifo_Init();
|
||||
void Fifo_Shutdown();
|
||||
|
@ -34,6 +34,9 @@
|
||||
|
||||
bool g_bRecordFifoData = false;
|
||||
|
||||
u8* g_video_buffer_read_ptr;
|
||||
static u8* s_video_buffer_pp_read_ptr;
|
||||
|
||||
static u32 InterpretDisplayList(u32 address, u32 size)
|
||||
{
|
||||
u8* old_pVideoData = g_video_buffer_read_ptr;
|
||||
@ -49,13 +52,10 @@ static u32 InterpretDisplayList(u32 address, u32 size)
|
||||
// Avoid the crash if Memory::GetPointer failed ..
|
||||
if (startAddress != nullptr)
|
||||
{
|
||||
g_video_buffer_read_ptr = startAddress;
|
||||
|
||||
// temporarily swap dl and non-dl (small "hack" for the stats)
|
||||
Statistics::SwapDL();
|
||||
|
||||
u8 *end = g_video_buffer_read_ptr + size;
|
||||
cycles = OpcodeDecoder_Run(end, true);
|
||||
OpcodeDecoder_Run(startAddress, startAddress + size, &cycles, true);
|
||||
INCSTAT(stats.thisFrame.numDListsCalled);
|
||||
|
||||
// un-swap
|
||||
@ -70,20 +70,17 @@ static u32 InterpretDisplayList(u32 address, u32 size)
|
||||
|
||||
static void InterpretDisplayListPreprocess(u32 address, u32 size)
|
||||
{
|
||||
u8* old_read_ptr = g_video_buffer_pp_read_ptr;
|
||||
u8* old_read_ptr = s_video_buffer_pp_read_ptr;
|
||||
u8* startAddress = Memory::GetPointer(address);
|
||||
|
||||
PushFifoAuxBuffer(startAddress, size);
|
||||
|
||||
if (startAddress != nullptr)
|
||||
{
|
||||
g_video_buffer_pp_read_ptr = startAddress;
|
||||
|
||||
u8 *end = startAddress + size;
|
||||
OpcodeDecoder_Preprocess(end, true);
|
||||
OpcodeDecoder_Preprocess(startAddress, startAddress + size, true);
|
||||
}
|
||||
|
||||
g_video_buffer_pp_read_ptr = old_read_ptr;
|
||||
s_video_buffer_pp_read_ptr = old_read_ptr;
|
||||
}
|
||||
|
||||
static void UnknownOpcode(u8 cmd_byte, void *buffer, bool preprocess)
|
||||
@ -315,33 +312,40 @@ void OpcodeDecoder_Shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
u32 OpcodeDecoder_Run(u8* end, bool in_display_list)
|
||||
u8* OpcodeDecoder_Run(u8* start, u8* end, u32* cycles, bool in_display_list)
|
||||
{
|
||||
g_video_buffer_read_ptr = start;
|
||||
u32 totalCycles = 0;
|
||||
while (true)
|
||||
{
|
||||
u8* old = g_video_buffer_read_ptr;
|
||||
u32 cycles = Decode</*is_preprocess*/ false, &g_video_buffer_read_ptr>(end, in_display_list);
|
||||
if (cycles == 0)
|
||||
u32 cycles_op = Decode</*is_preprocess*/ false, &g_video_buffer_read_ptr>(end, in_display_list);
|
||||
if (cycles_op == 0)
|
||||
{
|
||||
g_video_buffer_read_ptr = old;
|
||||
break;
|
||||
}
|
||||
totalCycles += cycles;
|
||||
totalCycles += cycles_op;
|
||||
}
|
||||
return totalCycles;
|
||||
if (cycles)
|
||||
{
|
||||
*cycles = totalCycles;
|
||||
}
|
||||
return g_video_buffer_read_ptr;
|
||||
}
|
||||
|
||||
void OpcodeDecoder_Preprocess(u8 *end, bool in_display_list)
|
||||
u8* OpcodeDecoder_Preprocess(u8* start, u8 *end, bool in_display_list)
|
||||
{
|
||||
s_video_buffer_pp_read_ptr = start;
|
||||
while (true)
|
||||
{
|
||||
u8* old = g_video_buffer_pp_read_ptr;
|
||||
u32 cycles = Decode</*is_preprocess*/ true, &g_video_buffer_pp_read_ptr>(end, in_display_list);
|
||||
u8* old = s_video_buffer_pp_read_ptr;
|
||||
u32 cycles = Decode</*is_preprocess*/ true, &s_video_buffer_pp_read_ptr>(end, in_display_list);
|
||||
if (cycles == 0)
|
||||
{
|
||||
g_video_buffer_pp_read_ptr = old;
|
||||
s_video_buffer_pp_read_ptr = old;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return s_video_buffer_pp_read_ptr;
|
||||
}
|
||||
|
@ -40,5 +40,5 @@ extern bool g_bRecordFifoData;
|
||||
|
||||
void OpcodeDecoder_Init();
|
||||
void OpcodeDecoder_Shutdown();
|
||||
u32 OpcodeDecoder_Run(u8* end, bool in_display_list);
|
||||
void OpcodeDecoder_Preprocess(u8* end, bool in_display_list);
|
||||
u8* OpcodeDecoder_Run(u8* start, u8* end, u32* cycles, bool in_display_list);
|
||||
u8* OpcodeDecoder_Preprocess(u8* start, u8* end, bool in_display_list);
|
||||
|
Loading…
Reference in New Issue
Block a user