Skip to content

Commit

Permalink
fifo need size
Browse files Browse the repository at this point in the history
  • Loading branch information
weihuoya committed Nov 7, 2018
1 parent ea29f95 commit 502fac0
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 34 deletions.
2 changes: 1 addition & 1 deletion Source/Android/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@
<string name="efb_copy_method">Store EFB Copies to Texture Only</string>
<string name="efb_copy_method_description">Stores EFB Copies exclusively on the GPU, bypassing system memory. Causes graphical defects in a small number of games. If unsure, leave this checked.</string>
<string name="defer_efb_copies">Defer EFB Copies to RAM</string>
<string name="defer_efb_copies_description">Waits until the game synchronizes with the emulated GPU before writing the contents of EFB copies to RAM. May result in faster performance. If unsure, leave this unchecked.</string>
<string name="defer_efb_copies_description">Waits until the game synchronizes with the emulated GPU before writing the contents of EFB copies to RAM. May result in faster performance.</string>
<string name="texture_cache">Texture Cache</string>
<string name="texture_cache_accuracy">Texture Cache Accuracy</string>
<string name="texture_cache_accuracy_description">The safer the selection, the less likely the emulator will be missing any texture updates from RAM.</string>
Expand Down
60 changes: 34 additions & 26 deletions Source/Core/VideoCommon/Fifo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,46 +329,50 @@ void RunGpuLoop()

CommandProcessor::SetCPStatusFromGPU();

u32 needSize = 0;
// check if we are able to run this buffer
while (!CommandProcessor::IsInterruptWaiting() && fifo.bFF_GPReadEnable &&
fifo.CPReadWriteDistance && !AtBreakpoint())
{
if (param.bSyncGPU && s_sync_ticks.load() < param.iSyncGpuMinDistance)
break;

u32 cyclesExecuted = 0;
u32 readPtr = fifo.CPReadPointer;
u32 readSize = ReadDataFromFifo(readPtr);

readPtr += readSize;
if (readPtr == fifo.CPEnd + 32)
readPtr = fifo.CPBase;

Common::AtomicStore(fifo.CPReadPointer, readPtr);
Common::AtomicAdd(fifo.CPReadWriteDistance, -(s32)readSize);

ASSERT_MSG(COMMANDPROCESSOR, (s32)fifo.CPReadWriteDistance - readSize >= 0,
"Negative fifo.CPReadWriteDistance = %i in FIFO Loop !\nThat can produce "
"instability in the game. Please report it.",
fifo.CPReadWriteDistance - readSize);

u8* write_ptr = s_video_buffer_write_ptr;
s_video_buffer_read_ptr = OpcodeDecoder::Run(
DataReader(s_video_buffer_read_ptr, write_ptr), &cyclesExecuted, false);

Common::AtomicStore(fifo.CPReadPointer, readPtr);
Common::AtomicAdd(fifo.CPReadWriteDistance, -(s32)readSize);
if ((write_ptr - s_video_buffer_read_ptr) == 0)
Common::AtomicStore(fifo.SafeCPReadPointer, fifo.CPReadPointer);

CommandProcessor::SetCPStatusFromGPU();

if (param.bSyncGPU)
if (write_ptr - s_video_buffer_read_ptr > needSize)
{
cyclesExecuted = (int)(cyclesExecuted / param.fSyncGpuOverclock);
int old = s_sync_ticks.fetch_sub(cyclesExecuted);
if (old >= param.iSyncGpuMaxDistance &&
old - (int)cyclesExecuted < param.iSyncGpuMaxDistance)
s_sync_wakeup_event.Set();
u32 cyclesExecuted = 0;
needSize = 0;
s_video_buffer_read_ptr = OpcodeDecoder::Run(
DataReader(s_video_buffer_read_ptr, write_ptr), &cyclesExecuted, false, &needSize);

if ((write_ptr - s_video_buffer_read_ptr) == 0)
Common::AtomicStore(fifo.SafeCPReadPointer, fifo.CPReadPointer);
CommandProcessor::SetCPStatusFromGPU();

if (param.bSyncGPU)
{
cyclesExecuted = (int)(cyclesExecuted / param.fSyncGpuOverclock);
int old = s_sync_ticks.fetch_sub(cyclesExecuted);
if (old >= param.iSyncGpuMaxDistance &&
old - (int)cyclesExecuted < param.iSyncGpuMaxDistance)
s_sync_wakeup_event.Set();
}
}

// This call is pretty important in DualCore mode and must be called in the FIFO Loop.
// If we don't, s_swapRequested or s_efbAccessRequested won't be set to false
// leading the CPU thread to wait in Video_BeginField or Video_AccessEFB thus slowing
Expand Down Expand Up @@ -440,11 +444,11 @@ void RunGpu()

static int RunGpuOnCpu(int ticks)
{
CommandProcessor::SCPFifoStruct& fifo = CommandProcessor::fifo;
bool reset_simd_state = false;
u32 need_size = 0;
int available_ticks = int(ticks * SConfig::GetInstance().fSyncGpuOverclock) + s_sync_ticks.load();
while (fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint() &&
available_ticks >= 0)
CommandProcessor::SCPFifoStruct& fifo = CommandProcessor::fifo;
while (fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint() && available_ticks >= 0)
{
u32 read_size;
if (s_use_deterministic_gpu_thread)
Expand All @@ -461,16 +465,20 @@ static int RunGpuOnCpu(int ticks)
reset_simd_state = true;
}
read_size = ReadDataFromFifo(fifo.CPReadPointer);
u32 cycles = 0;
s_video_buffer_read_ptr = OpcodeDecoder::Run(
DataReader(s_video_buffer_read_ptr, s_video_buffer_write_ptr), &cycles, false);
available_ticks -= cycles;
u8* write_ptr = s_video_buffer_write_ptr;
if (write_ptr - s_video_buffer_read_ptr > need_size)
{
u32 cycles = 0;
need_size = 0;
s_video_buffer_read_ptr = OpcodeDecoder::Run(
DataReader(s_video_buffer_read_ptr, write_ptr), &cycles, false, &need_size);
available_ticks -= cycles;
}
}

fifo.CPReadPointer += read_size;
if (fifo.CPReadPointer == fifo.CPEnd + 32)
fifo.CPReadPointer = fifo.CPBase;

fifo.CPReadWriteDistance -= read_size;
}

Expand Down
44 changes: 38 additions & 6 deletions Source/Core/VideoCommon/OpcodeDecoding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,18 +81,22 @@ void Init()
}

template <bool is_preprocess>
u8* Run(DataReader src, u32* cycles, bool in_display_list)
u8* Run(DataReader src, u32* cycles, bool in_display_list, u32* need_size)
{
int refarray;
u32 totalCycles = 0;
u8* opcodeStart;
u32 totalCycles = 0;
u32 needSize = 0;
while (true)
{
opcodeStart = src.GetPointer();
if (!src.size())
{
needSize = 1;
goto end;
}

u8 cmd_byte = src.Read<u8>();
u8 cmd_byte = *opcodeStart; src.Skip();
switch (cmd_byte)
{
case GX_NOP:
Expand All @@ -107,7 +111,10 @@ u8* Run(DataReader src, u32* cycles, bool in_display_list)
case GX_LOAD_CP_REG:
{
if (src.size() < 1 + 4)
{
needSize = 5;
goto end;
}
totalCycles += 12;
u8 sub_cmd = src.Read<u8>();
u32 value = src.Read<u32>();
Expand All @@ -120,11 +127,17 @@ u8* Run(DataReader src, u32* cycles, bool in_display_list)
case GX_LOAD_XF_REG:
{
if (src.size() < 4)
{
needSize = 4;
goto end;
}
u32 Cmd2 = src.Read<u32>();
int transfer_size = ((Cmd2 >> 16) & 15) + 1;
if (src.size() < transfer_size * sizeof(u32))
{
needSize = transfer_size * sizeof(u32);
goto end;
}
totalCycles += 18 + 6 * transfer_size;
if (!is_preprocess)
{
Expand All @@ -151,7 +164,10 @@ u8* Run(DataReader src, u32* cycles, bool in_display_list)
goto load_indx;
load_indx:
if (src.size() < 4)
{
needSize = 4;
goto end;
}
totalCycles += 6;
if (is_preprocess)
PreprocessIndexedXF(src.Read<u32>(), refarray);
Expand All @@ -162,7 +178,10 @@ u8* Run(DataReader src, u32* cycles, bool in_display_list)
case GX_CMD_CALL_DL:
{
if (src.size() < 8)
{
needSize = 8;
goto end;
}
u32 address = src.Read<u32>();
u32 count = src.Read<u32>();

Expand Down Expand Up @@ -197,7 +216,10 @@ u8* Run(DataReader src, u32* cycles, bool in_display_list)
// tokens and stuff. TODO: Call a much simplified LoadBPReg instead.
{
if (src.size() < 4)
{
needSize = 4;
goto end;
}
totalCycles += 12;
u32 bp_cmd = src.Read<u32>();
if (is_preprocess)
Expand All @@ -218,7 +240,10 @@ u8* Run(DataReader src, u32* cycles, bool in_display_list)
{
// load vertices
if (src.size() < 2)
{
needSize = 2;
goto end;
}
u16 num_vertices = src.Read<u16>();
if(num_vertices > 0)
{
Expand All @@ -227,8 +252,11 @@ u8* Run(DataReader src, u32* cycles, bool in_display_list)
int bytes =
VertexLoaderManager::GetVertexSize(vtx_attr_group, is_preprocess) * num_vertices;

if (bytes > src.size())
if (src.size() < bytes)
{
needSize = bytes;
goto end;
}

if(!is_preprocess)
VertexLoaderManager::RunVertices(vtx_attr_group, primitive, num_vertices, src);
Expand Down Expand Up @@ -265,10 +293,14 @@ u8* Run(DataReader src, u32* cycles, bool in_display_list)
{
*cycles = totalCycles;
}
if (need_size)
{
*need_size = needSize;
}
return opcodeStart;
}

template u8* Run<true>(DataReader src, u32* cycles, bool in_display_list);
template u8* Run<false>(DataReader src, u32* cycles, bool in_display_list);
template u8* Run<true>(DataReader src, u32* cycles, bool in_display_list, u32* need_size);
template u8* Run<false>(DataReader src, u32* cycles, bool in_display_list, u32* need_size);

} // namespace OpcodeDecoder
2 changes: 1 addition & 1 deletion Source/Core/VideoCommon/OpcodeDecoding.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,6 @@ enum
void Init();

template <bool is_preprocess = false>
u8* Run(DataReader src, u32* cycles, bool in_display_list);
u8* Run(DataReader src, u32* cycles, bool in_display_list, u32* need_size = nullptr);

} // namespace OpcodeDecoder

0 comments on commit 502fac0

Please sign in to comment.