示例#1
0
bool FifoCommandRunnable()
{
	u32 buffer_size = (u32)(GetVideoBufferEndPtr() - g_pVideoData);
    if (buffer_size == 0)
		return false;  // can't peek

	u8 cmd_byte = DataPeek8(0);	
    u32 command_size = 0;

    switch (cmd_byte)
    {
    case GX_NOP: // Hm, this means that we scan over nop streams pretty slowly...
	case GX_CMD_INVL_VC: // Invalidate Vertex Cache - no parameters
    case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that
        command_size = 1;
        break;

	case GX_LOAD_BP_REG:	
        command_size = 5;
        break;

    case GX_LOAD_CP_REG:
        command_size = 6;
        break;

    case GX_LOAD_INDX_A:
    case GX_LOAD_INDX_B:
    case GX_LOAD_INDX_C:
    case GX_LOAD_INDX_D:
        command_size = 5;
        break;

    case GX_CMD_CALL_DL:	
        command_size = 9;
        break;

    case GX_LOAD_XF_REG:
        {
            // check if we can read the header
            if (buffer_size >= 5)
			{				
                command_size = 1 + 4;
                u32 Cmd2 = DataPeek32(1);
                int transfer_size = ((Cmd2 >> 16) & 15) + 1;
                command_size += transfer_size * 4;				
            }
            else
			{
                return false;
            }			
        }
示例#2
0
文件: Fifo.cpp 项目: Chiri23/dolphin
// Description: Main FIFO update loop
// Purpose: Keep the Core HW updated about the CPU-GPU distance
void RunGpuLoop()
{
	std::lock_guard<std::mutex> lk(m_csHWVidOccupied);
	GpuRunningState = true;
	SCPFifoStruct &fifo = CommandProcessor::fifo;
	u32 cyclesExecuted = 0;

	while (GpuRunningState)
	{
		g_video_backend->PeekMessages();

		VideoFifo_CheckAsyncRequest();

		CommandProcessor::SetCpStatus();

		Common::AtomicStore(CommandProcessor::VITicks, CommandProcessor::m_cpClockOrigin);

		// check if we are able to run this buffer
		while (GpuRunningState && !CommandProcessor::interruptWaiting && fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint())
		{
			fifo.isGpuReadingData = true;
			CommandProcessor::isPossibleWaitingSetDrawDone = fifo.bFF_GPLinkEnable ? true : false;

			if (!Core::g_CoreStartupParameter.bSyncGPU || Common::AtomicLoad(CommandProcessor::VITicks) > CommandProcessor::m_cpClockOrigin)
			{
				u32 readPtr = fifo.CPReadPointer;
				u8 *uData = Memory::GetPointer(readPtr);

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

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

				ReadDataFromFifo(uData, 32);

				cyclesExecuted = OpcodeDecoder_Run(g_bSkipCurrentFrame);

				if (Core::g_CoreStartupParameter.bSyncGPU && Common::AtomicLoad(CommandProcessor::VITicks) > cyclesExecuted)
					Common::AtomicAdd(CommandProcessor::VITicks, -(s32)cyclesExecuted);

				Common::AtomicStore(fifo.CPReadPointer, readPtr);
				Common::AtomicAdd(fifo.CPReadWriteDistance, -32);
				if ((GetVideoBufferEndPtr() - g_pVideoData) == 0)
					Common::AtomicStore(fifo.SafeCPReadPointer, fifo.CPReadPointer);
			}

			CommandProcessor::SetCpStatus();

			// 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 things down.
			VideoFifo_CheckAsyncRequest();
			CommandProcessor::isPossibleWaitingSetDrawDone = false;
		}

		fifo.isGpuReadingData = false;

		if (EmuRunningState)
		{
			// NOTE(jsd): Calling SwitchToThread() on Windows 7 x64 is a hot spot, according to profiler.
			// See https://docs.google.com/spreadsheet/ccc?key=0Ah4nh0yGtjrgdFpDeF9pS3V6RUotRVE3S3J4TGM1NlE#gid=0
			// for benchmark details.
#if 0
			Common::YieldCPU();
#endif
		}
		else
		{
			// While the emu is paused, we still handle async requests then sleep.
			while (!EmuRunningState)
			{
				g_video_backend->PeekMessages();
				m_csHWVidOccupied.unlock();
				Common::SleepCurrentThread(1);
				m_csHWVidOccupied.lock();
			}
		}
	}
}
示例#3
0
u32 FifoCommandRunnable(u32 &command_size)
{
	u32 cycleTime = 0;
	u32 buffer_size = (u32)(GetVideoBufferEndPtr() - g_pVideoData);
	if (buffer_size == 0)
		return 0;  // can't peek

	u8 cmd_byte = DataPeek8(0);

	switch (cmd_byte)
	{
	case GX_NOP: // Hm, this means that we scan over nop streams pretty slowly...
		command_size = 1;
		cycleTime = 6;
		break;
	case GX_CMD_INVL_VC: // Invalidate Vertex Cache - no parameters
		command_size = 1;
		cycleTime = 6;
		break;
	case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that
		command_size = 1;
		cycleTime = 6;
		break;

	case GX_LOAD_BP_REG:
		command_size = 5;
		cycleTime = 12;
		break;

	case GX_LOAD_CP_REG:
		command_size = 6;
		cycleTime = 12;
		break;

	case GX_LOAD_INDX_A:
	case GX_LOAD_INDX_B:
	case GX_LOAD_INDX_C:
	case GX_LOAD_INDX_D:
		command_size = 5;
		cycleTime = 6; // TODO
		break;

	case GX_CMD_CALL_DL:
		{
			// FIXME: Calculate the cycle time of the display list.
			//u32 address = DataPeek32(1);
			//u32 size = DataPeek32(5);
			//u8* old_pVideoData = g_pVideoData;
			//u8* startAddress = Memory::GetPointer(address);

			//// Avoid the crash if Memory::GetPointer failed ..
			//if (startAddress != 0)
			//{
			//	g_pVideoData = startAddress;
			//	u8 *end = g_pVideoData + size;
			//	u32 step = 0;
			//	while (g_pVideoData < end)
			//	{
			//		cycleTime += FifoCommandRunnable(step);
			//		g_pVideoData += step;
			//	}
			//}
			//else
			//{
			//	cycleTime = 45;
			//}

			//// reset to the old pointer
			//g_pVideoData = old_pVideoData;
			command_size = 9;
			cycleTime = 45;  // This is unverified
		}
		break;

	case GX_LOAD_XF_REG:
		{
			// check if we can read the header
			if (buffer_size >= 5)
			{
				command_size = 1 + 4;
				u32 Cmd2 = DataPeek32(1);
				int transfer_size = ((Cmd2 >> 16) & 15) + 1;
				command_size += transfer_size * 4;
				cycleTime = 18 + 6 * transfer_size;
			}
			else
			{
				return 0;
			}
		}