async-iso: First iteration of the experimental read-ahead system.

In this iteration, a simple read-ahead scheme is used where the next expected read begins as soon as the CDVD code calls FinishRead.
The expected improvement is close to 0 since a similar system is already in place in the core.

The next iteration should have an internal buffer, and use completion callbacks to initiate read-aheads as soon as the previous read is done, without waiting for the emulator to fetch the results of the previous operation.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5486 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
gigaherz 2012-12-28 01:42:39 +00:00
parent ac28815316
commit d2f3b4a7fc
9 changed files with 91 additions and 16 deletions

View File

@ -674,6 +674,7 @@ typedef s32 (CALLBACK* _CDVDctrlTrayOpen)();
typedef s32 (CALLBACK* _CDVDctrlTrayClose)(); typedef s32 (CALLBACK* _CDVDctrlTrayClose)();
typedef s32 (CALLBACK* _CDVDreadSector)(u8* buffer, u32 lsn, int mode); typedef s32 (CALLBACK* _CDVDreadSector)(u8* buffer, u32 lsn, int mode);
typedef s32 (CALLBACK* _CDVDgetDualInfo)(s32* dualType, u32* _layer1start); typedef s32 (CALLBACK* _CDVDgetDualInfo)(s32* dualType, u32* _layer1start);
typedef void (CALLBACK* _CDVDnotifyReadLength)(s32 readLength);
typedef void (CALLBACK* _CDVDnewDiskCB)(void (*callback)()); typedef void (CALLBACK* _CDVDnewDiskCB)(void (*callback)());

View File

@ -10,12 +10,14 @@
class AsyncFileReader class AsyncFileReader
{ {
protected: protected:
AsyncFileReader(void) {} AsyncFileReader(void) { m_nextExpectedRead = -1; }
wxString m_filename; wxString m_filename;
uint m_blocksize; uint m_blocksize;
uint m_nextExpectedRead;
public: public:
virtual ~AsyncFileReader(void) {}; virtual ~AsyncFileReader(void) {};
@ -32,6 +34,8 @@ public:
virtual uint GetBlockCount(void) const=0; virtual uint GetBlockCount(void) const=0;
virtual void SetBlockSize(uint bytes) {} virtual void SetBlockSize(uint bytes) {}
uint GetReadAheadHint() const { return m_nextExpectedRead; }
uint GetBlockSize() const { return m_blocksize; } uint GetBlockSize() const { return m_blocksize; }
@ -73,7 +77,7 @@ public:
virtual void Close(void); virtual void Close(void);
virtual uint GetBlockCount(void) const; virtual uint GetBlockCount(void) const;
void SetBlockSize(uint bytes) { m_blocksize = bytes; } void SetBlockSize(uint bytes) { m_blocksize = bytes; }
}; };

View File

@ -598,9 +598,12 @@ void SaveStateBase::cdvdFreeze()
// Make sure the Cdvd plugin has the expected track loaded into the buffer. // Make sure the Cdvd plugin has the expected track loaded into the buffer.
// If cdvd.Readed is cleared it means we need to load the SeekToSector (ie, a // If cdvd.Readed is cleared it means we need to load the SeekToSector (ie, a
// seek is in progress!) // seek is in progress!)
if( cdvd.Reading ) if( cdvd.Reading )
{
DoCDVDnotifyReadLength(cdvd.nSectors);
cdvd.RErr = DoCDVDreadTrack( cdvd.Readed ? cdvd.Sector : cdvd.SeekToSector, cdvd.ReadMode); cdvd.RErr = DoCDVDreadTrack( cdvd.Readed ? cdvd.Sector : cdvd.SeekToSector, cdvd.ReadMode);
}
} }
} }
@ -1218,6 +1221,8 @@ static void cdvdWrite04(u8 rt) { // NCOMMAND
cdvd.ReadTime = cdvdBlockReadTime( MODE_CDROM ); cdvd.ReadTime = cdvdBlockReadTime( MODE_CDROM );
CDVDREAD_INT( cdvdStartSeek( cdvd.SeekToSector,MODE_CDROM ) ); CDVDREAD_INT( cdvdStartSeek( cdvd.SeekToSector,MODE_CDROM ) );
DoCDVDnotifyReadLength(cdvd.nSectors);
// Read-ahead by telling the plugin about the track now. // Read-ahead by telling the plugin about the track now.
// This helps improve performance on actual from-cd emulation // This helps improve performance on actual from-cd emulation
@ -1266,6 +1271,8 @@ static void cdvdWrite04(u8 rt) { // NCOMMAND
cdvd.ReadTime = cdvdBlockReadTime( MODE_CDROM ); cdvd.ReadTime = cdvdBlockReadTime( MODE_CDROM );
CDVDREAD_INT( cdvdStartSeek( cdvd.SeekToSector, MODE_CDROM ) ); CDVDREAD_INT( cdvdStartSeek( cdvd.SeekToSector, MODE_CDROM ) );
DoCDVDnotifyReadLength(cdvd.nSectors);
// Read-ahead by telling the plugin about the track now. // Read-ahead by telling the plugin about the track now.
// This helps improve performance on actual from-cd emulation // This helps improve performance on actual from-cd emulation
@ -1302,6 +1309,8 @@ static void cdvdWrite04(u8 rt) { // NCOMMAND
cdvd.ReadTime = cdvdBlockReadTime( MODE_DVDROM ); cdvd.ReadTime = cdvdBlockReadTime( MODE_DVDROM );
CDVDREAD_INT( cdvdStartSeek( cdvd.SeekToSector, MODE_DVDROM ) ); CDVDREAD_INT( cdvdStartSeek( cdvd.SeekToSector, MODE_DVDROM ) );
DoCDVDnotifyReadLength(cdvd.nSectors);
// Read-ahead by telling the plugin about the track now. // Read-ahead by telling the plugin about the track now.
// This helps improve performance on actual from-cd emulation // This helps improve performance on actual from-cd emulation

View File

@ -419,6 +419,11 @@ s32 DoCDVDreadSector(u8* buffer, u32 lsn, int mode)
return ret; return ret;
} }
void DoCDVDnotifyReadLength(s32 length)
{
CDVD->notifyReadLength(length);
}
s32 DoCDVDreadTrack(u32 lsn, int mode) s32 DoCDVDreadTrack(u32 lsn, int mode)
{ {
CheckNullCDVD(); CheckNullCDVD();

View File

@ -51,6 +51,7 @@ struct CDVD_API
_CDVDreadSector readSector; _CDVDreadSector readSector;
_CDVDgetBuffer2 getBuffer2; _CDVDgetBuffer2 getBuffer2;
_CDVDgetDualInfo getDualInfo; _CDVDgetDualInfo getDualInfo;
_CDVDnotifyReadLength notifyReadLength;
}; };
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -80,3 +81,4 @@ extern s32 DoCDVDgetBuffer(u8* buffer);
extern s32 DoCDVDdetectDiskType(); extern s32 DoCDVDdetectDiskType();
extern void DoCDVDresetDiskTypeCache(); extern void DoCDVDresetDiskTypeCache();
extern void DoCDVDnotifyReadLength(s32 length);

View File

@ -475,6 +475,11 @@ void CALLBACK ISOnewDiskCB(void(* /* callback */)())
{ {
} }
void CALLBACK ISOnotifyReadLength(s32 readLength)
{
iso.NotifyReadLength(readLength);
}
CDVD_API CDVDapi_Iso = CDVD_API CDVDapi_Iso =
{ {
ISOclose, ISOclose,
@ -496,4 +501,5 @@ CDVD_API CDVDapi_Iso =
ISOreadSector, ISOreadSector,
ISOgetBuffer2, ISOgetBuffer2,
ISOgetDualInfo, ISOgetDualInfo,
ISOnotifyReadLength
}; };

View File

@ -50,6 +50,18 @@ int InputIsoFile::ReadSync(u8* dst, uint lsn)
void InputIsoFile::BeginRead2(uint lsn) void InputIsoFile::BeginRead2(uint lsn)
{ {
if(m_read_inprogress)
{
if(lsn >= m_read_lsn && lsn < (m_read_lsn+m_read_count))
{
// read already in progress
return;
}
FinishRead3(NULL, 0);
m_is_reading_ahead = false;
}
if (lsn > m_blocks) if (lsn > m_blocks)
{ {
FastFormatUnicode msg; FastFormatUnicode msg;
@ -98,12 +110,22 @@ int InputIsoFile::FinishRead3(u8* dst, uint mode)
if(m_read_inprogress) if(m_read_inprogress)
{ {
ret = m_reader->FinishRead(); if(dst)
ret = m_reader->FinishRead();
else
{
m_reader->CancelRead();
return -1;
}
m_read_inprogress = false; m_read_inprogress = false;
if(ret < 0) if(ret < 0)
return ret; return ret;
} }
if(!dst)
return -1;
switch (mode) switch (mode)
{ {
@ -153,6 +175,22 @@ int InputIsoFile::FinishRead3(u8* dst, uint mode)
dst[diff - 9] = 2; dst[diff - 9] = 2;
} }
if(m_expected_sequential_remaining > 0)
m_expected_sequential_remaining --;
if(m_read_ahead > 0 && (m_expected_sequential_remaining > 0 || m_read_length > 1))
{
uint lsn = (m_expected_sequential_remaining > 0) ?
m_read_lsn + 1 :
m_reader->GetReadAheadHint();
if(lsn >= 0)
{
m_is_reading_ahead = true;
BeginRead2(lsn);
}
}
return 0; return 0;
} }
@ -179,6 +217,11 @@ void InputIsoFile::_init()
m_read_inprogress = false; m_read_inprogress = false;
m_read_count = 0; m_read_count = 0;
m_read_lsn = -1; m_read_lsn = -1;
m_read_length = 0;
m_expected_sequential_remaining = 0;
m_is_reading_ahead = false;
} }
// Tests the specified filename to see if it is a supported ISO type. This function typically // Tests the specified filename to see if it is a supported ISO type. This function typically
@ -218,7 +261,9 @@ bool InputIsoFile::Open( const wxString& srcfile, bool testOnly )
m_reader = bdr; m_reader = bdr;
ReadUnit = 1; ReadUnit = 1;
m_read_ahead = 0;
} }
bool detected = Detect(); bool detected = Detect();
@ -239,6 +284,8 @@ bool InputIsoFile::Open( const wxString& srcfile, bool testOnly )
// Returns the original reader if single-part or a Multipart reader otherwise // Returns the original reader if single-part or a Multipart reader otherwise
m_reader = MultipartFileReader::DetectMultipart(m_reader); m_reader = MultipartFileReader::DetectMultipart(m_reader);
m_read_ahead = MaxReadAhead;
} }
m_blocks = m_reader->GetBlockCount(); m_blocks = m_reader->GetBlockCount();

View File

@ -37,7 +37,8 @@ class InputIsoFile
{ {
DeclareNoncopyableObject( InputIsoFile ); DeclareNoncopyableObject( InputIsoFile );
static const uint MaxReadUnit = 128; static const uint MaxReadUnit = 1;
static const uint MaxReadAhead = 1;
protected: protected:
uint ReadUnit; uint ReadUnit;
@ -63,7 +64,13 @@ protected:
uint m_read_lsn; uint m_read_lsn;
uint m_read_count; uint m_read_count;
u8 m_readbuffer[MaxReadUnit * CD_FRAMESIZE_RAW]; u8 m_readbuffer[MaxReadUnit * CD_FRAMESIZE_RAW];
uint m_read_ahead;
uint m_read_length;
bool m_is_reading_ahead;
uint m_expected_sequential_remaining;
public: public:
InputIsoFile(); InputIsoFile();
virtual ~InputIsoFile() throw(); virtual ~InputIsoFile() throw();
@ -88,6 +95,8 @@ public:
void BeginRead2(uint lsn); void BeginRead2(uint lsn);
int FinishRead3(u8* dest, uint mode); int FinishRead3(u8* dest, uint mode);
void NotifyReadLength(s32 length) { m_expected_sequential_remaining = m_read_length = length; }
protected: protected:
void _init(); void _init();

View File

@ -34,16 +34,6 @@ bool FlatFileReader::Open(const wxString& fileName)
int FlatFileReader::ReadSync(void* pBuffer, uint sector, uint count) int FlatFileReader::ReadSync(void* pBuffer, uint sector, uint count)
{ {
//LARGE_INTEGER offset;
//offset.QuadPart = sector * (__int64)m_blocksize;
//
//DWORD bytesToRead = count * m_blocksize;
//DWORD bytes;
//if(!ReadFile(hOverlappedFile, pBuffer, bytesToRead, &bytes, NULL))
// return -1;
//return bytes;
BeginRead(pBuffer, sector, count); BeginRead(pBuffer, sector, count);
return FinishRead(); return FinishRead();
} }
@ -62,6 +52,8 @@ void FlatFileReader::BeginRead(void* pBuffer, uint sector, uint count)
ReadFile(hOverlappedFile, pBuffer, bytesToRead, NULL, &asyncOperationContext); ReadFile(hOverlappedFile, pBuffer, bytesToRead, NULL, &asyncOperationContext);
asyncInProgress = true; asyncInProgress = true;
m_nextExpectedRead = sector + count;
} }
int FlatFileReader::FinishRead(void) int FlatFileReader::FinishRead(void)