mirror of https://github.com/PCSX2/pcsx2.git
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:
parent
ac28815316
commit
d2f3b4a7fc
|
@ -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)());
|
||||||
|
|
||||||
|
|
|
@ -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; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue