mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-10 16:19:28 +01:00
Merge pull request #4598 from stenzek/fifoplayer
FifoPlayer: Loop playback consistency, save texture memory to file
This commit is contained in:
commit
0e279b6312
@ -65,6 +65,9 @@ bool FifoDataFile::Save(const std::string& filename)
|
|||||||
u64 xfRegsOffset = file.Tell();
|
u64 xfRegsOffset = file.Tell();
|
||||||
file.WriteArray(m_XFRegs, XF_REGS_SIZE);
|
file.WriteArray(m_XFRegs, XF_REGS_SIZE);
|
||||||
|
|
||||||
|
u64 texMemOffset = file.Tell();
|
||||||
|
file.WriteArray(m_TexMem, TEX_MEM_SIZE);
|
||||||
|
|
||||||
// Write header
|
// Write header
|
||||||
FileHeader header;
|
FileHeader header;
|
||||||
header.fileId = FILE_ID;
|
header.fileId = FILE_ID;
|
||||||
@ -83,6 +86,9 @@ bool FifoDataFile::Save(const std::string& filename)
|
|||||||
header.xfRegsOffset = xfRegsOffset;
|
header.xfRegsOffset = xfRegsOffset;
|
||||||
header.xfRegsSize = XF_REGS_SIZE;
|
header.xfRegsSize = XF_REGS_SIZE;
|
||||||
|
|
||||||
|
header.texMemOffset = texMemOffset;
|
||||||
|
header.texMemSize = TEX_MEM_SIZE;
|
||||||
|
|
||||||
header.frameListOffset = frameListOffset;
|
header.frameListOffset = frameListOffset;
|
||||||
header.frameCount = (u32)m_Frames.size();
|
header.frameCount = (u32)m_Frames.size();
|
||||||
|
|
||||||
@ -150,22 +156,31 @@ std::unique_ptr<FifoDataFile> FifoDataFile::Load(const std::string& filename, bo
|
|||||||
return dataFile;
|
return dataFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 size = std::min((u32)BP_MEM_SIZE, header.bpMemSize);
|
u32 size = std::min<u32>(BP_MEM_SIZE, header.bpMemSize);
|
||||||
file.Seek(header.bpMemOffset, SEEK_SET);
|
file.Seek(header.bpMemOffset, SEEK_SET);
|
||||||
file.ReadArray(dataFile->m_BPMem, size);
|
file.ReadArray(dataFile->m_BPMem, size);
|
||||||
|
|
||||||
size = std::min((u32)CP_MEM_SIZE, header.cpMemSize);
|
size = std::min<u32>(CP_MEM_SIZE, header.cpMemSize);
|
||||||
file.Seek(header.cpMemOffset, SEEK_SET);
|
file.Seek(header.cpMemOffset, SEEK_SET);
|
||||||
file.ReadArray(dataFile->m_CPMem, size);
|
file.ReadArray(dataFile->m_CPMem, size);
|
||||||
|
|
||||||
size = std::min((u32)XF_MEM_SIZE, header.xfMemSize);
|
size = std::min<u32>(XF_MEM_SIZE, header.xfMemSize);
|
||||||
file.Seek(header.xfMemOffset, SEEK_SET);
|
file.Seek(header.xfMemOffset, SEEK_SET);
|
||||||
file.ReadArray(dataFile->m_XFMem, size);
|
file.ReadArray(dataFile->m_XFMem, size);
|
||||||
|
|
||||||
size = std::min((u32)XF_REGS_SIZE, header.xfRegsSize);
|
size = std::min<u32>(XF_REGS_SIZE, header.xfRegsSize);
|
||||||
file.Seek(header.xfRegsOffset, SEEK_SET);
|
file.Seek(header.xfRegsOffset, SEEK_SET);
|
||||||
file.ReadArray(dataFile->m_XFRegs, size);
|
file.ReadArray(dataFile->m_XFRegs, size);
|
||||||
|
|
||||||
|
// Texture memory saving was added in version 4.
|
||||||
|
std::memset(dataFile->m_TexMem, 0, TEX_MEM_SIZE);
|
||||||
|
if (dataFile->m_Version >= 4)
|
||||||
|
{
|
||||||
|
size = std::min<u32>(TEX_MEM_SIZE, header.texMemSize);
|
||||||
|
file.Seek(header.texMemOffset, SEEK_SET);
|
||||||
|
file.ReadArray(dataFile->m_TexMem, size);
|
||||||
|
}
|
||||||
|
|
||||||
// Read frames
|
// Read frames
|
||||||
for (u32 i = 0; i < header.frameCount; ++i)
|
for (u32 i = 0; i < header.frameCount; ++i)
|
||||||
{
|
{
|
||||||
|
@ -51,6 +51,7 @@ public:
|
|||||||
CP_MEM_SIZE = 256,
|
CP_MEM_SIZE = 256,
|
||||||
XF_MEM_SIZE = 4096,
|
XF_MEM_SIZE = 4096,
|
||||||
XF_REGS_SIZE = 96,
|
XF_REGS_SIZE = 96,
|
||||||
|
TEX_MEM_SIZE = 1024 * 1024,
|
||||||
};
|
};
|
||||||
|
|
||||||
FifoDataFile();
|
FifoDataFile();
|
||||||
@ -64,6 +65,7 @@ public:
|
|||||||
u32* GetCPMem() { return m_CPMem; }
|
u32* GetCPMem() { return m_CPMem; }
|
||||||
u32* GetXFMem() { return m_XFMem; }
|
u32* GetXFMem() { return m_XFMem; }
|
||||||
u32* GetXFRegs() { return m_XFRegs; }
|
u32* GetXFRegs() { return m_XFRegs; }
|
||||||
|
u8* GetTexMem() { return m_TexMem; }
|
||||||
void AddFrame(const FifoFrameInfo& frameInfo);
|
void AddFrame(const FifoFrameInfo& frameInfo);
|
||||||
const FifoFrameInfo& GetFrame(u32 frame) const { return m_Frames[frame]; }
|
const FifoFrameInfo& GetFrame(u32 frame) const { return m_Frames[frame]; }
|
||||||
u32 GetFrameCount() const { return static_cast<u32>(m_Frames.size()); }
|
u32 GetFrameCount() const { return static_cast<u32>(m_Frames.size()); }
|
||||||
@ -90,6 +92,7 @@ private:
|
|||||||
u32 m_CPMem[CP_MEM_SIZE];
|
u32 m_CPMem[CP_MEM_SIZE];
|
||||||
u32 m_XFMem[XF_MEM_SIZE];
|
u32 m_XFMem[XF_MEM_SIZE];
|
||||||
u32 m_XFRegs[XF_REGS_SIZE];
|
u32 m_XFRegs[XF_REGS_SIZE];
|
||||||
|
u8 m_TexMem[TEX_MEM_SIZE];
|
||||||
|
|
||||||
u32 m_Flags;
|
u32 m_Flags;
|
||||||
u32 m_Version;
|
u32 m_Version;
|
||||||
|
@ -11,7 +11,7 @@ namespace FifoFileStruct
|
|||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
FILE_ID = 0x0d01f1f0,
|
FILE_ID = 0x0d01f1f0,
|
||||||
VERSION_NUMBER = 3,
|
VERSION_NUMBER = 4,
|
||||||
MIN_LOADER_VERSION = 1,
|
MIN_LOADER_VERSION = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -34,6 +34,8 @@ union FileHeader {
|
|||||||
u64 frameListOffset;
|
u64 frameListOffset;
|
||||||
u32 frameCount;
|
u32 frameCount;
|
||||||
u32 flags;
|
u32 flags;
|
||||||
|
u64 texMemOffset;
|
||||||
|
u32 texMemSize;
|
||||||
};
|
};
|
||||||
u32 rawData[32];
|
u32 rawData[32];
|
||||||
};
|
};
|
||||||
|
@ -25,6 +25,10 @@
|
|||||||
#include "VideoCommon/BPMemory.h"
|
#include "VideoCommon/BPMemory.h"
|
||||||
#include "VideoCommon/CommandProcessor.h"
|
#include "VideoCommon/CommandProcessor.h"
|
||||||
|
|
||||||
|
// We need to include TextureDecoder.h for the texMem array.
|
||||||
|
// TODO: Move texMem somewhere else so this isn't an issue.
|
||||||
|
#include "VideoCommon/TextureDecoder.h"
|
||||||
|
|
||||||
bool IsPlayingBackFifologWithBrokenEFBCopies = false;
|
bool IsPlayingBackFifologWithBrokenEFBCopies = false;
|
||||||
|
|
||||||
FifoPlayer::~FifoPlayer()
|
FifoPlayer::~FifoPlayer()
|
||||||
@ -122,7 +126,13 @@ int FifoPlayer::AdvanceFrame()
|
|||||||
if (m_FrameRangeStart >= m_FrameRangeEnd)
|
if (m_FrameRangeStart >= m_FrameRangeEnd)
|
||||||
return CPU::CPU_STEPPING;
|
return CPU::CPU_STEPPING;
|
||||||
|
|
||||||
|
// When looping, reload the contents of all the BP/CP/CF registers.
|
||||||
|
// This ensures that each time the first frame is played back, the state of the
|
||||||
|
// GPU is the same for each playback loop.
|
||||||
m_CurrentFrame = m_FrameRangeStart;
|
m_CurrentFrame = m_FrameRangeStart;
|
||||||
|
LoadRegisters();
|
||||||
|
LoadTextureMemory();
|
||||||
|
FlushWGP();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_FrameWrittenCb)
|
if (m_FrameWrittenCb)
|
||||||
@ -414,7 +424,13 @@ void FifoPlayer::LoadMemory()
|
|||||||
PowerPC::IBATUpdated();
|
PowerPC::IBATUpdated();
|
||||||
|
|
||||||
SetupFifo();
|
SetupFifo();
|
||||||
|
LoadRegisters();
|
||||||
|
LoadTextureMemory();
|
||||||
|
FlushWGP();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FifoPlayer::LoadRegisters()
|
||||||
|
{
|
||||||
const u32* regs = m_File->GetBPMem();
|
const u32* regs = m_File->GetBPMem();
|
||||||
for (int i = 0; i < FifoDataFile::BP_MEM_SIZE; ++i)
|
for (int i = 0; i < FifoDataFile::BP_MEM_SIZE; ++i)
|
||||||
{
|
{
|
||||||
@ -448,8 +464,13 @@ void FifoPlayer::LoadMemory()
|
|||||||
regs = m_File->GetXFRegs();
|
regs = m_File->GetXFRegs();
|
||||||
for (int i = 0; i < FifoDataFile::XF_REGS_SIZE; ++i)
|
for (int i = 0; i < FifoDataFile::XF_REGS_SIZE; ++i)
|
||||||
LoadXFReg(i, regs[i]);
|
LoadXFReg(i, regs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
FlushWGP();
|
void FifoPlayer::LoadTextureMemory()
|
||||||
|
{
|
||||||
|
static_assert(static_cast<size_t>(TMEM_SIZE) == static_cast<size_t>(FifoDataFile::TEX_MEM_SIZE),
|
||||||
|
"TMEM_SIZE matches the size of texture memory in FifoDataFile");
|
||||||
|
std::memcpy(texMem, m_File->GetTexMem(), FifoDataFile::TEX_MEM_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FifoPlayer::WriteCP(u32 address, u16 value)
|
void FifoPlayer::WriteCP(u32 address, u16 value)
|
||||||
@ -514,6 +535,7 @@ bool FifoPlayer::ShouldLoadBP(u8 address)
|
|||||||
case BPMEM_PE_TOKEN_INT_ID:
|
case BPMEM_PE_TOKEN_INT_ID:
|
||||||
case BPMEM_TRIGGER_EFB_COPY:
|
case BPMEM_TRIGGER_EFB_COPY:
|
||||||
case BPMEM_LOADTLUT1:
|
case BPMEM_LOADTLUT1:
|
||||||
|
case BPMEM_PRELOAD_MODE:
|
||||||
case BPMEM_PERF1:
|
case BPMEM_PERF1:
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
|
@ -110,6 +110,8 @@ private:
|
|||||||
void SetupFifo();
|
void SetupFifo();
|
||||||
|
|
||||||
void LoadMemory();
|
void LoadMemory();
|
||||||
|
void LoadRegisters();
|
||||||
|
void LoadTextureMemory();
|
||||||
|
|
||||||
void WriteCP(u32 address, u16 value);
|
void WriteCP(u32 address, u16 value);
|
||||||
void WritePI(u32 address, u32 value);
|
void WritePI(u32 address, u32 value);
|
||||||
|
@ -183,7 +183,7 @@ void FifoRecorder::EndFrame(u32 fifoStart, u32 fifoEnd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FifoRecorder::SetVideoMemory(const u32* bpMem, const u32* cpMem, const u32* xfMem,
|
void FifoRecorder::SetVideoMemory(const u32* bpMem, const u32* cpMem, const u32* xfMem,
|
||||||
const u32* xfRegs, u32 xfRegsSize)
|
const u32* xfRegs, u32 xfRegsSize, const u8* texMem)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::recursive_mutex> lk(sMutex);
|
std::lock_guard<std::recursive_mutex> lk(sMutex);
|
||||||
|
|
||||||
@ -195,6 +195,8 @@ void FifoRecorder::SetVideoMemory(const u32* bpMem, const u32* cpMem, const u32*
|
|||||||
|
|
||||||
u32 xfRegsCopySize = std::min((u32)FifoDataFile::XF_REGS_SIZE, xfRegsSize);
|
u32 xfRegsCopySize = std::min((u32)FifoDataFile::XF_REGS_SIZE, xfRegsSize);
|
||||||
memcpy(m_File->GetXFRegs(), xfRegs, xfRegsCopySize * 4);
|
memcpy(m_File->GetXFRegs(), xfRegs, xfRegsCopySize * 4);
|
||||||
|
|
||||||
|
memcpy(m_File->GetTexMem(), texMem, FifoDataFile::TEX_MEM_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
FifoRecordAnalyzer::Initialize(cpMem);
|
FifoRecordAnalyzer::Initialize(cpMem);
|
||||||
|
@ -37,7 +37,7 @@ public:
|
|||||||
// bpMem must point to the actual bp mem array used by the plugin because it will be read as fifo
|
// bpMem must point to the actual bp mem array used by the plugin because it will be read as fifo
|
||||||
// data is recorded
|
// data is recorded
|
||||||
void SetVideoMemory(const u32* bpMem, const u32* cpMem, const u32* xfMem, const u32* xfRegs,
|
void SetVideoMemory(const u32* bpMem, const u32* cpMem, const u32* xfMem, const u32* xfRegs,
|
||||||
u32 xfRegsSize);
|
u32 xfRegsSize, const u8* texMem);
|
||||||
|
|
||||||
// Checked once per frame prior to callng EndFrame()
|
// Checked once per frame prior to callng EndFrame()
|
||||||
bool IsRecording() const { return m_IsRecording; }
|
bool IsRecording() const { return m_IsRecording; }
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
#include "VideoCommon/RenderBase.h"
|
#include "VideoCommon/RenderBase.h"
|
||||||
#include "VideoCommon/Statistics.h"
|
#include "VideoCommon/Statistics.h"
|
||||||
#include "VideoCommon/TextureCacheBase.h"
|
#include "VideoCommon/TextureCacheBase.h"
|
||||||
|
#include "VideoCommon/TextureDecoder.h"
|
||||||
#include "VideoCommon/VideoConfig.h"
|
#include "VideoCommon/VideoConfig.h"
|
||||||
#include "VideoCommon/XFMemory.h"
|
#include "VideoCommon/XFMemory.h"
|
||||||
|
|
||||||
@ -678,7 +679,8 @@ void Renderer::RecordVideoMemory()
|
|||||||
|
|
||||||
FillCPMemoryArray(cpmem);
|
FillCPMemoryArray(cpmem);
|
||||||
|
|
||||||
FifoRecorder::GetInstance().SetVideoMemory(bpmem_ptr, cpmem, xfmem_ptr, xfregs_ptr, xfregs_size);
|
FifoRecorder::GetInstance().SetVideoMemory(bpmem_ptr, cpmem, xfmem_ptr, xfregs_ptr, xfregs_size,
|
||||||
|
texMem);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc,
|
void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user