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