From 63b254c8bd5d68f720f1246a2e015eb3db4ffac5 Mon Sep 17 00:00:00 2001 From: "Jake.Stine" Date: Tue, 16 Nov 2010 15:58:42 +0000 Subject: [PATCH] newHostVM: * Applied the new RecompiledCodeReserve to the VIF recompilers (saves another 4-8mb of memory, depending on game). * Fixed a bug in pxsFmt / FastFormatUnicode (string formatting). * Final round of error handling cleanups. (branch is basically ready for re-integration -- needs some testin for obvious/show stopping bugs, thanks!) git-svn-id: http://pcsx2.googlecode.com/svn/branches/newHostVM@4025 96395faa-99c1-11dd-bbfe-3dabce05a288 --- common/include/Utilities/PageFaultSource.h | 10 +-- common/src/Utilities/FastFormatString.cpp | 4 +- common/src/Utilities/VirtualMemory.cpp | 35 ++++++--- pcsx2/CMakeLists.txt | 1 - pcsx2/Linux/pcsx2.cbp | 1 - pcsx2/System.cpp | 55 ++++++++++---- pcsx2/System.h | 9 ++- pcsx2/System/RecTypes.h | 4 +- pcsx2/gui/AppAssert.cpp | 37 ++++------ pcsx2/windows/VCprojects/pcsx2_2008.vcproj | 4 - pcsx2/x86/iR3000A.cpp | 9 +-- pcsx2/x86/ix86-32/iR5900-32.cpp | 19 +---- pcsx2/x86/microVU.cpp | 3 +- pcsx2/x86/newVif.h | 33 +++++---- pcsx2/x86/newVif_BlockBuffer.h | 86 ---------------------- pcsx2/x86/newVif_Dynarec.cpp | 44 +++++------ pcsx2/x86/newVif_Unpack.cpp | 17 +++++ 17 files changed, 161 insertions(+), 210 deletions(-) delete mode 100644 pcsx2/x86/newVif_BlockBuffer.h diff --git a/common/include/Utilities/PageFaultSource.h b/common/include/Utilities/PageFaultSource.h index 07ea665d06..41fd4c0924 100644 --- a/common/include/Utilities/PageFaultSource.h +++ b/common/include/Utilities/PageFaultSource.h @@ -127,10 +127,9 @@ class VirtualMemoryReserve { DeclareNoncopyableObject( VirtualMemoryReserve ); -public: - wxString Name; - protected: + wxString m_name; + // Default size of the reserve, in bytes. Can be specified when the object is contructed. // Is used as the reserve size when Reserve() is called, unless an override is specified // in the Reserve parameters. @@ -149,7 +148,7 @@ protected: uptr m_pages_commited; public: - VirtualMemoryReserve( const wxString& name, size_t size = 0 ); + VirtualMemoryReserve( const wxString& name=wxEmptyString, size_t size = 0 ); virtual ~VirtualMemoryReserve() throw() { Release(); @@ -167,7 +166,7 @@ public: virtual bool Commit(); bool IsOk() const { return m_baseptr != NULL; } - wxString GetName() const { return Name; } + wxString GetName() const { return m_name; } uptr GetReserveSizeInBytes() const { return m_pages_reserved * __pagesize; } uptr GetReserveSizeInPages() const { return m_pages_reserved; } @@ -179,6 +178,7 @@ public: u8* GetPtrEnd() { return (u8*)m_baseptr + (m_pages_reserved * __pagesize); } const u8* GetPtrEnd() const { return (u8*)m_baseptr + (m_pages_reserved * __pagesize); } + VirtualMemoryReserve& SetName( const wxString& newname ); VirtualMemoryReserve& SetBaseAddr( uptr newaddr ); VirtualMemoryReserve& SetPageAccessOnCommit( const PageProtectionMode& mode ); diff --git a/common/src/Utilities/FastFormatString.cpp b/common/src/Utilities/FastFormatString.cpp index 175a8ae27c..b08e14bdbd 100644 --- a/common/src/Utilities/FastFormatString.cpp +++ b/common/src/Utilities/FastFormatString.cpp @@ -174,7 +174,7 @@ static __ri void format_that_ascii_mess( CharBufferType& buffer, uint writepos, len += writepos; if (len < size) break; - buffer.Alloc( len + 128 ); + buffer.Resize( len + 128 ); }; // performing an assertion or log of a truncated string is unsafe, so let's not; even @@ -205,7 +205,7 @@ static __ri uint format_that_unicode_mess( CharBufferType& buffer, uint writepos len += writepos; if (len < size) return len; - buffer.Alloc( (len + 128) * sizeof(wxChar) ); + buffer.Resize( (len + 128) * sizeof(wxChar) ); }; // performing an assertion or log of a truncated string is unsafe, so let's not; even diff --git a/common/src/Utilities/VirtualMemory.cpp b/common/src/Utilities/VirtualMemory.cpp index 1812ade3a7..69369ec3e9 100644 --- a/common/src/Utilities/VirtualMemory.cpp +++ b/common/src/Utilities/VirtualMemory.cpp @@ -71,7 +71,7 @@ void SrcType_PageFault::_DispatchRaw( ListenerIterator iter, const ListenerItera // VirtualMemoryReserve (implementations) // -------------------------------------------------------------------------------------- VirtualMemoryReserve::VirtualMemoryReserve( const wxString& name, size_t size ) - : Name( name ) + : m_name( name ) { m_defsize = size; @@ -81,6 +81,12 @@ VirtualMemoryReserve::VirtualMemoryReserve( const wxString& name, size_t size ) m_prot_mode = PageAccess_None(); } +VirtualMemoryReserve& VirtualMemoryReserve::SetName( const wxString& newname ) +{ + m_name = newname; + return *this; +} + VirtualMemoryReserve& VirtualMemoryReserve::SetBaseAddr( uptr newaddr ) { if (!pxAssertDev(!m_pages_reserved, "Invalid object state: you must release the virtual memory reserve prior to changing its base address!")) return *this; @@ -124,7 +130,7 @@ void* VirtualMemoryReserve::Reserve( size_t size, uptr base, uptr upper_bounds ) if (!m_baseptr || (upper_bounds != 0 && (((uptr)m_baseptr + reserved_bytes) > upper_bounds))) { DevCon.Warning( L"%s: host memory @ 0x%08x -> 0x%08x is unavailable; attempting to map elsewhere...", - Name.c_str(), base, base + size ); + m_name.c_str(), base, base + size ); SafeSysMunmap(m_baseptr, reserved_bytes); @@ -143,9 +149,16 @@ void* VirtualMemoryReserve::Reserve( size_t size, uptr base, uptr upper_bounds ) } if (!m_baseptr) return NULL; - - DevCon.WriteLn( Color_Blue, L"%-32s @ 0x%08X -> 0x%08X [%umb]", Name.c_str(), - m_baseptr, (uptr)m_baseptr+reserved_bytes, reserved_bytes / _1mb); + + FastFormatUnicode mbkb; + uint mbytes = reserved_bytes / _1mb; + if (mbytes) + mbkb.Write( "[%umb]", mbytes ); + else + mbkb.Write( "[%ukb]", reserved_bytes / 1024 ); + + DevCon.WriteLn( Color_Gray, L"%-32s @ 0x%08p -> 0x%08p %s", m_name.c_str(), + m_baseptr, (uptr)m_baseptr+reserved_bytes, mbkb.c_str()); return m_baseptr; } @@ -193,17 +206,17 @@ bool VirtualMemoryReserve::TryResize( uint newsize ) uint toReservePages = newPages - m_pages_reserved; uint toReserveBytes = toReservePages * __pagesize; - DevCon.WriteLn( L"%-32s is being expanded by %u pages.", Name.c_str(), toReservePages); + DevCon.WriteLn( L"%-32s is being expanded by %u pages.", m_name.c_str(), toReservePages); m_baseptr = (void*)HostSys::MmapReserve((uptr)GetPtrEnd(), toReserveBytes); if (!m_baseptr) { Console.Warning("%-32s could not be passively resized due to virtual memory conflict!"); - Console.Indent().Warning("(attempted to map memory @ 0x%08X -> 0x%08X", m_baseptr, (uptr)m_baseptr+toReserveBytes); + Console.Indent().Warning("(attempted to map memory @ 0x%08p -> 0x%08p", m_baseptr, (uptr)m_baseptr+toReserveBytes); } - DevCon.WriteLn( Color_Blue, L"%-32s @ 0x%08X -> 0x%08X [%umb]", Name.c_str(), + DevCon.WriteLn( Color_Gray, L"%-32s @ 0x%08p -> 0x%08p [%umb]", m_name.c_str(), m_baseptr, (uptr)m_baseptr+toReserveBytes, toReserveBytes / _1mb); } else if (newPages < m_pages_reserved) @@ -213,11 +226,11 @@ bool VirtualMemoryReserve::TryResize( uint newsize ) uint toRemovePages = m_pages_reserved - newPages; uint toRemoveBytes = toRemovePages * __pagesize; - DevCon.WriteLn( L"%-32s is being shrunk by %u pages.", Name.c_str(), toRemovePages); + DevCon.WriteLn( L"%-32s is being shrunk by %u pages.", m_name.c_str(), toRemovePages); HostSys::MmapResetPtr(GetPtrEnd(), toRemoveBytes); - DevCon.WriteLn( Color_Blue, L"%-32s @ 0x%08X -> 0x%08X [%umb]", Name.c_str(), + DevCon.WriteLn( Color_Gray, L"%-32s @ 0x%08p -> 0x%08p [%umb]", m_name.c_str(), m_baseptr, (uptr)m_baseptr+toRemoveBytes, toRemoveBytes / _1mb); } @@ -244,7 +257,7 @@ void BaseVmReserveListener::CommitBlocks( uptr page, uint blocks ) // physical ram or virtual memory. if (!HostSys::MmapCommitPtr(blockptr, blocksbytes, m_prot_mode)) { - throw Exception::OutOfMemory(Name) + throw Exception::OutOfMemory(m_name) .SetDiagMsg(pxsFmt("An additional %u blocks @ 0x%08x were requested, but could not be committed!", blocks, blockptr)); } diff --git a/pcsx2/CMakeLists.txt b/pcsx2/CMakeLists.txt index 82957bf97c..cdbbc3342a 100644 --- a/pcsx2/CMakeLists.txt +++ b/pcsx2/CMakeLists.txt @@ -541,7 +541,6 @@ set(pcsx2x86Headers x86/microVU_Tables.inl x86/microVU_Upper.inl x86/newVif.h - x86/newVif_BlockBuffer.h x86/newVif_HashBucket.h x86/newVif_UnpackSSE.h x86/sVU_Compare.h diff --git a/pcsx2/Linux/pcsx2.cbp b/pcsx2/Linux/pcsx2.cbp index d3855a71c4..8722a0c032 100644 --- a/pcsx2/Linux/pcsx2.cbp +++ b/pcsx2/Linux/pcsx2.cbp @@ -646,7 +646,6 @@ - diff --git a/pcsx2/System.cpp b/pcsx2/System.cpp index 400fb27738..eb3dd07a3a 100644 --- a/pcsx2/System.cpp +++ b/pcsx2/System.cpp @@ -17,6 +17,7 @@ #include "Common.h" #include "IopCommon.h" #include "VUmicro.h" +#include "newVif.h" #include "SamplProf.h" @@ -30,9 +31,6 @@ #include "Utilities/MemsetFast.inl" -extern void closeNewVif(int idx); -extern void resetNewVif(int idx); - // -------------------------------------------------------------------------------------- // RecompiledCodeReserve (implementations) // -------------------------------------------------------------------------------------- @@ -108,6 +106,23 @@ void RecompiledCodeReserve::OnCommittedBlock( void* block ) } } +// This error message is shared by R5900, R3000, and microVU recompilers. It is not used by the +// SuperVU recompiler, since it has its own customized message. +void RecompiledCodeReserve::ThrowIfNotOk() const +{ + if (IsOk()) return; + + throw Exception::OutOfMemory(m_name) + .SetDiagMsg(pxsFmt( L"Recompiled code cache could not be mapped." )) + .SetUserMsg( pxE( ".Error:Recompiler:VirtualMemoryAlloc", + L"This recompiler was unable to reserve contiguous memory required for internal caches. " + L"This error can be caused by low virtual memory resources, such as a small or disabled swapfile, " + L"or by another program that is hogging a lot of memory. You can also try reducing the default " + L"cache sizes for all PCSX2 recompilers, found under Host Settings." + )); +} + + void SysOutOfMemory_EmergencyResponse(uptr blocksize) { // An out of memory error occurred. All we can try to do in response is reset the various @@ -346,11 +361,15 @@ void SysMainMemory::ReserveAll() { pxInstallSignalHandler(); - DevCon.WriteLn( "PS2vm: Mapping host memory for all virtual systems..." ); + DevCon.WriteLn( Color_StrongBlue, "Mapping host memory for virtual systems..." ); + ConsoleIndentScope indent(1); m_ee.Reserve(); m_iop.Reserve(); m_vu.Reserve(); + + reserveNewVif(0); + reserveNewVif(1); } void SysMainMemory::CommitAll() @@ -358,7 +377,8 @@ void SysMainMemory::CommitAll() vtlb_Core_Alloc(); if (m_ee.IsCommitted() && m_iop.IsCommitted() && m_vu.IsCommitted()) return; - DevCon.WriteLn( "PS2vm: Allocating host memory for all virtual systems..." ); + DevCon.WriteLn( Color_StrongBlue, "Allocating host memory for virtual systems..." ); + ConsoleIndentScope indent(1); m_ee.Commit(); m_iop.Commit(); @@ -370,23 +390,30 @@ void SysMainMemory::ResetAll() { CommitAll(); - DevCon.WriteLn( "PS2vm: Resetting host memory for all virtual systems..." ); + DevCon.WriteLn( Color_StrongBlue, "Resetting host memory for virtual systems..." ); + ConsoleIndentScope indent(1); m_ee.Reset(); m_iop.Reset(); m_vu.Reset(); + + // Note: newVif is reset as part of other VIF structures. } void SysMainMemory::DecommitAll() { if (!m_ee.IsCommitted() && !m_iop.IsCommitted() && !m_vu.IsCommitted()) return; - Console.WriteLn( "PS2vm: Decommitting host memory for all virtual systems..." ); + Console.WriteLn( Color_Blue, "Decommitting host memory for virtual systems..." ); + ConsoleIndentScope indent(1); m_ee.Decommit(); m_iop.Decommit(); m_vu.Decommit(); + closeNewVif(0); + closeNewVif(1); + vtlb_Core_Free(); } @@ -394,10 +421,14 @@ void SysMainMemory::ReleaseAll() { DecommitAll(); - Console.WriteLn( "PS2vm: Releasing host memory maps for all virtual systems..." ); + Console.WriteLn( Color_Blue, "Releasing host memory maps for virtual systems..." ); + ConsoleIndentScope indent(1); vtlb_Core_Free(); // Just to be sure... (calling order could result in it getting missed during Decommit). + releaseNewVif(0); + releaseNewVif(1); + m_ee.Decommit(); m_iop.Decommit(); m_vu.Decommit(); @@ -411,7 +442,8 @@ void SysMainMemory::ReleaseAll() // -------------------------------------------------------------------------------------- SysCpuProviderPack::SysCpuProviderPack() { - Console.WriteLn( "Reserving memory for recompilers..." ); + Console.WriteLn( Color_StrongBlue, "Reserving memory for recompilers..." ); + ConsoleIndentScope indent(1); CpuProviders = new CpuInitializerSet(); @@ -453,9 +485,6 @@ void SysCpuProviderPack::CleanupMess() throw() { try { - closeNewVif(0); - closeNewVif(1); - psxRec.Shutdown(); recCpu.Shutdown(); } @@ -574,5 +603,5 @@ wxString SysGetDiscID() // region and revision). } - return wxsFormat( L"%8.8x", ElfCRC ); + return pxsFmt( L"%08x", ElfCRC ); } diff --git a/pcsx2/System.h b/pcsx2/System.h index dd34f0f117..43159f08d3 100644 --- a/pcsx2/System.h +++ b/pcsx2/System.h @@ -61,11 +61,18 @@ namespace HostMemoryMap // IOP recompiler code cache area (16 or 32mb) static const uptr IOPrec = 0x34000000; + // newVif0 recompiler code cache area (16mb) + static const uptr VIF0rec = 0x36000000; + + // newVif1 recompiler code cache area (32mb) + static const uptr VIF1rec = 0x38000000; + // microVU1 recompiler code cache area (32 or 64mb) - static const uptr mVU0rec = 0x38000000; + static const uptr mVU0rec = 0x3C000000; // microVU0 recompiler code cache area (64mb) static const uptr mVU1rec = 0x40000000; + } // -------------------------------------------------------------------------------------- diff --git a/pcsx2/System/RecTypes.h b/pcsx2/System/RecTypes.h index 1fec845da1..2c26e3702c 100644 --- a/pcsx2/System/RecTypes.h +++ b/pcsx2/System/RecTypes.h @@ -37,7 +37,7 @@ protected: bool m_profiler_registered; public: - RecompiledCodeReserve( const wxString& name, uint defCommit = 0 ); + RecompiledCodeReserve( const wxString& name=wxEmptyString, uint defCommit = 0 ); virtual ~RecompiledCodeReserve() throw(); virtual void* Reserve( size_t size, uptr base=0, uptr upper_bounds=0 ); @@ -48,6 +48,8 @@ public: { return SetProfilerName( fromUTF8(shortname) ); } + + void ThrowIfNotOk() const; operator void*() { return m_baseptr; } operator const void*() const { return m_baseptr; } diff --git a/pcsx2/gui/AppAssert.cpp b/pcsx2/gui/AppAssert.cpp index c6b754b92e..d729c1a5b0 100644 --- a/pcsx2/gui/AppAssert.cpp +++ b/pcsx2/gui/AppAssert.cpp @@ -22,10 +22,10 @@ class StackDump : public wxStackWalker { protected: - wxString m_stackTrace; - wxString m_srcFuncName; - bool m_ignoreDone; - int m_skipped; + FastFormatUnicode m_stackTrace; + wxString m_srcFuncName; + bool m_ignoreDone; + int m_skipped; public: StackDump( const FnChar_t* src_function_name ) @@ -37,17 +37,12 @@ public: m_skipped = 0; } - const wxString& GetStackTrace() const { return m_stackTrace; } + const wxChar* GetStackTrace() const { return m_stackTrace.c_str(); } protected: virtual void OnStackFrame(const wxStackFrame& frame) { - wxString name( frame.GetName() ); - if( name.IsEmpty() ) - { - name = wxsFormat( L"%p ", frame.GetAddress() ); - } - /*else if( m_srcFuncName.IsEmpty() || m_srcFuncName == name ) + /*if( m_srcFuncName.IsEmpty() || m_srcFuncName == name ) { // FIXME: This logic isn't reliable yet. // It's possible for our debug information to not match the function names returned by @@ -71,27 +66,25 @@ protected: return; }*/ - //wxString briefName; - wxString essenName; + m_stackTrace.Write(pxsFmt( L"[%02d]", frame.GetLevel()-m_skipped)); + + if (!frame.GetName().IsEmpty()) + m_stackTrace.Write(pxsFmt( L" %-44s", frame.GetName().c_str() )); + else + m_stackTrace.Write(pxsFmt( L" 0x%-42p", frame.GetAddress() )); if( frame.HasSourceLocation() ) { wxFileName wxfn(frame.GetFileName()); - //briefName.Printf( L"(%s:%d)", wxfn.GetFullName().c_str(), frame.GetLine() ); wxfn.SetVolume( wxEmptyString ); - //int count = wxfn.GetDirCount(); for( int i=0; i<2; ++i ) wxfn.RemoveDir(0); - essenName.Printf( L"%s:%d", wxfn.GetFullPath().c_str(), frame.GetLine() ); + m_stackTrace.Write( L" %s:%d", wxfn.GetFullPath().c_str(), frame.GetLine() ); } - - m_stackTrace += pxsFmt( L"[%02d] %-44s %s\n", - frame.GetLevel()-m_skipped, - name.c_str(), - essenName.c_str() - ); + + m_stackTrace.Write(L"\n"); } }; diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj index f648745cb0..129822dfc8 100644 --- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj +++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj @@ -839,10 +839,6 @@ RelativePath="..\..\x86\newVif.h" > - - diff --git a/pcsx2/x86/iR3000A.cpp b/pcsx2/x86/iR3000A.cpp index 795f671f28..941125e3d8 100644 --- a/pcsx2/x86/iR3000A.cpp +++ b/pcsx2/x86/iR3000A.cpp @@ -757,8 +757,6 @@ static const uint m_recBlockAllocSize = static void recReserveCache() { - extern wxString GetMsg_RecVmFailed(); - if (!recMem) recMem = new RecompiledCodeReserve(L"R3000A Recompiler Cache", _1mb * 2); recMem->SetProfilerName("IOPrec"); @@ -771,12 +769,7 @@ static void recReserveCache() m_ConfiguredCacheReserve /= 2; } - if (!recMem->IsOk()) - { - throw Exception::VirtualMemoryMapConflict(recMem->GetName()) - .SetDiagMsg(pxsFmt( L"Recompiled code cache could not be mapped." )) - .SetUserMsg(GetMsg_RecVmFailed()); - } + recMem->ThrowIfNotOk(); } static void recReserve() diff --git a/pcsx2/x86/ix86-32/iR5900-32.cpp b/pcsx2/x86/ix86-32/iR5900-32.cpp index 874b452765..2be0fafd9c 100644 --- a/pcsx2/x86/ix86-32/iR5900-32.cpp +++ b/pcsx2/x86/ix86-32/iR5900-32.cpp @@ -578,18 +578,6 @@ static void recThrowHardwareDeficiency( const wxChar* extFail ) .SetUserMsg(pxsFmt(_("%s Extensions not found. The R5900-32 recompiler requires a host CPU with MMX, SSE, and SSE2 extensions."), extFail )); } -// This error message is shared by R5900, R3000, and microVU recompilers. It is not used by the -// SuperVU recompiler, since it has its own customized message. -wxString GetMsg_RecVmFailed() -{ - return pxE( ".Error:Recompiler:VirtualMemoryAlloc", - L"This recompiler was unable to reserve contiguous memory required for internal caches. " - L"This error can be caused by low virtual memory resources, such as a small or disabled swapfile, " - L"or by another program that is hogging a lot of memory. You can also try reducing the default " - L"cache sizes for all PCSX2 recompilers, found under Host Settings." - ); -} - static void recReserveCache() { if (!recMem) recMem = new RecompiledCodeReserve(L"R5900-32 Recompiler Cache", _1mb * 4); @@ -604,12 +592,7 @@ static void recReserveCache() m_ConfiguredCacheReserve /= 2; } - if (!recMem->IsOk()) - { - throw Exception::VirtualMemoryMapConflict(recMem->GetName()) - .SetDiagMsg(pxsFmt( L"Recompiled code cache could not be mapped." )) - .SetUserMsg(GetMsg_RecVmFailed()); - } + recMem->ThrowIfNotOk(); } static void recReserve() diff --git a/pcsx2/x86/microVU.cpp b/pcsx2/x86/microVU.cpp index b01d1cb904..a1bbaf3872 100644 --- a/pcsx2/x86/microVU.cpp +++ b/pcsx2/x86/microVU.cpp @@ -94,8 +94,7 @@ void microVU::reserveCache() (u8*)cache_reserve->Reserve( cacheSize * _1mb, HostMemoryMap::mVU1rec ) : (u8*)cache_reserve->Reserve( cacheSize * _1mb, HostMemoryMap::mVU0rec ); - if(!cache_reserve->IsOk()) - throw Exception::VirtualMemoryMapConflict().SetDiagMsg(pxsFmt( L"Micro VU%u Recompiler Cache", index )); + cache_reserve->ThrowIfNotOk(); } // Only run this once per VU! ;) diff --git a/pcsx2/x86/newVif.h b/pcsx2/x86/newVif.h index 7f63bb6b91..d61456b395 100644 --- a/pcsx2/x86/newVif.h +++ b/pcsx2/x86/newVif.h @@ -19,6 +19,8 @@ #include "VU.h" #include "x86emitter/x86emitter.h" +#include "RecTypes.h" + using namespace x86Emitter; #define aMax(x, y) std::max(x,y) @@ -28,13 +30,14 @@ using namespace x86Emitter; typedef u32 (__fastcall *nVifCall)(void*, const void*); typedef void (__fastcall *nVifrecCall)(uptr dest, uptr src); -#include "newVif_BlockBuffer.h" #include "newVif_HashBucket.h" extern void mVUmergeRegs(const xRegisterSSE& dest, const xRegisterSSE& src, int xyzw, bool modXYZW = 0); extern void _nVifUnpack (int idx, const u8* data, uint mode, bool isFill); +extern void dVifReserve (int idx); extern void dVifReset (int idx); extern void dVifClose (int idx); +extern void dVifRelease (int idx); extern void VifUnpackSSE_Init(); _vifT extern void dVifUnpack (const u8* data, bool isFill); @@ -76,23 +79,25 @@ struct nVifStruct { u32 bSize; // Size of 'buffer' u32 bPtr; - u32 idx; // VIF0 or VIF1 - u8* recPtr; // Cur Pos to recompile to - u8* recEnd; // 'Safe' End of Rec Cache - BlockBuffer* vifCache; // Block Buffer + uint recReserveSizeMB; // reserve size, in megabytes. + RecompiledCodeReserve* recReserve; + u8* recWritePtr; // current write pos into the reserve + HashBucket<_tParams>* vifBlocks; // Vif Blocks int numBlocks; // # of Blocks Recompiled - - nVifStruct() - { - vifCache = NULL; - vifBlocks = NULL; - numBlocks = 0; - recPtr = NULL; - recEnd = NULL; - } + + // VIF0 or VIF1 - provided for debugging helpfulness only, and is generally unused. + // (templates are used for most or all VIF indexing) + u32 idx; + + nVifStruct(); }; +extern void reserveNewVif(int idx); +extern void closeNewVif(int idx); +extern void resetNewVif(int idx); +extern void releaseNewVif(int idx); + extern __aligned16 nVifStruct nVif[2]; extern __aligned16 nVifCall nVifUpk[(2*2*16)*4]; // ([USN][Masking][Unpack Type]) [curCycle] extern __aligned16 u32 nVifMask[3][4][4]; // [MaskNumber][CycleNumber][Vector] diff --git a/pcsx2/x86/newVif_BlockBuffer.h b/pcsx2/x86/newVif_BlockBuffer.h deleted file mode 100644 index 532c613819..0000000000 --- a/pcsx2/x86/newVif_BlockBuffer.h +++ /dev/null @@ -1,86 +0,0 @@ -/* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2010 PCSX2 Dev Team - * - * PCSX2 is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with PCSX2. - * If not, see . - */ - -#pragma once - -// Allocates a Chunk of memory using SysMmapEx... -// This memory can be used to write recompiled code to. -// Its got basic resizing/growing ability too, but probably -// won't be too useful since growing the block buffer will -// invalidate any pointers pointing to the old block buffer. -// (so remember to invalidate those block pointers :D) -// It also deallocates itself on 'delete', so you can -// just use 'new' and 'delete' for initialization and -// deletion/cleanup respectfully... -class BlockBuffer { -protected: - u32 mSize; // Cur Size (in bytes) - u32 mSizeT; // Total Size (in bytes) - u32 mGrowBy; // amount to grow by when buffer fills (in bytes) - u8* mData; // Data Ptr (allocated via SysMmap) - - void alloc(int size) { - mData = SysMmapEx(0, size, 0, "nVif_BlockBuffer"); - if (!mData) throw Exception::OutOfMemory(L"nVif recompiled code buffer (nVif_BlockBuffer)"); - clear(); - } - void dealloc(u8* &dPtr, int size) { - SafeSysMunmap( dPtr, size ); - } - -public: - virtual ~BlockBuffer() throw() { - dealloc(mData, mSizeT); - } - - BlockBuffer(u32 tSize, u32 growby=_1mb*2) { - mSizeT = tSize; - mGrowBy = growby; - mSize = 0; - alloc(mSizeT); - } - - void append(void *addr, u32 size) { - if ((mSize + size) > mSizeT) grow(mSizeT + mGrowBy); - memcpy_fast(&mData[mSize], addr, size); - mSize += size; - } - - // Increases the allocation size. Warning: Unlike 'realloc' this function will - // CLEAR all contents of the buffer. This is because copying contents of recompiled - // caches is mostly useless since it invalidates any pointers into the block. - // (code relocation techniques are possible, but are difficult, potentially slow, - // and easily bug prone. Not recommended at this time). --air - void grow(u32 newSize) { - pxAssume( newSize > mSizeT ); - u8* temp = mData; - alloc(newSize); - dealloc(temp, mSizeT); - clear(); - mSizeT = newSize; - } - - // clears the entire buffer to recompiler fill (0xcc), and sets mSize to 0. - // (indicating none of the buffer is allocated). - void clear() { - if( mSize == 0 ) return; // no clears needed if nothing's been written/modified - mSize = 0; - memset(mData, 0xcc, mSizeT); - } - - u32 getCurSize() { return mSize; } - u32 getAllocSize() { return mSizeT; } - u8* getBlock() { return mData; } -}; diff --git a/pcsx2/x86/newVif_Dynarec.cpp b/pcsx2/x86/newVif_Dynarec.cpp index 8325341da5..d5656b2292 100644 --- a/pcsx2/x86/newVif_Dynarec.cpp +++ b/pcsx2/x86/newVif_Dynarec.cpp @@ -22,34 +22,37 @@ static __aligned16 nVifBlock _vBlock = {0}; -void dVifReset(int idx) { - // If the VIF cache is greater than 12mb, then it's due for a complete reset back - // down to a reasonable starting point of 4mb. - if( nVif[idx].vifCache && (nVif[idx].vifCache->getAllocSize() > _1mb*12) ) - safe_delete(nVif[idx].vifCache); +void dVifReserve(int idx) +{ + if (!nVif[idx].recReserve) + nVif[idx].recReserve = new RecompiledCodeReserve(pxsFmt(L"VIF%u Unpack Recompiler Cache", idx)); - if( !nVif[idx].vifCache ) - nVif[idx].vifCache = new BlockBuffer(_1mb*4); - else - nVif[idx].vifCache->clear(); + nVif[idx].recReserve->Reserve( nVif[idx].recReserveSizeMB * _1mb, idx ? HostMemoryMap::VIF1rec : HostMemoryMap::VIF0rec ); +} + +void dVifReset(int idx) { if( !nVif[idx].vifBlocks ) nVif[idx].vifBlocks = new HashBucket<_tParams>(); else nVif[idx].vifBlocks->clear(); - nVif[idx].numBlocks = 0; - - nVif[idx].recPtr = nVif[idx].vifCache->getBlock(); - nVif[idx].recEnd = &nVif[idx].recPtr[nVif[idx].vifCache->getAllocSize()-(_1mb/4)]; // .25mb Safe Zone + nVif[idx].recReserve->Reset(); + nVif[idx].numBlocks = 0; + nVif[idx].recWritePtr = nVif[idx].recReserve->GetPtr(); } void dVifClose(int idx) { nVif[idx].numBlocks = 0; - safe_delete(nVif[idx].vifCache); + nVif[idx].recReserve->Reset(); + safe_delete(nVif[idx].vifBlocks); } +void dVifRelease(int idx) { + safe_delete(nVif[idx].recReserve); +} + VifUnpackSSE_Dynarec::VifUnpackSSE_Dynarec(const nVifStruct& vif_, const nVifBlock& vifBlock_) : v(vif_) , vB(vifBlock_) @@ -223,11 +226,10 @@ _vifT static __fi u8* dVifsetVUptr(uint cl, uint wl, bool isFill) { // [TODO] : Finish implementing support for VIF's growable recBlocks buffer. Currently // it clears the buffer only. static __fi void dVifRecLimit(int idx) { - if (nVif[idx].recPtr > nVif[idx].recEnd) { - DevCon.WriteLn("nVif Rec - Out of Rec Cache! [%x > %x]", nVif[idx].recPtr, nVif[idx].recEnd); - nVif[idx].vifBlocks->clear(); - nVif[idx].recPtr = nVif[idx].vifCache->getBlock(); - nVif[idx].recEnd = &nVif[idx].recPtr[nVif[idx].vifCache->getAllocSize()-(_1mb/4)]; // .25mb Safe Zone + if (nVif[idx].recWritePtr > (nVif[idx].recReserve->GetPtrEnd() - _256kb)) { + DevCon.WriteLn("nVif Recompiler Cache Reset! [0x%08x > 0x%08x]", nVif[idx].recWritePtr, nVif[idx].recReserve->GetPtrEnd()); + nVif[idx].recReserve->Reset(); + nVif[idx].recWritePtr = nVif[idx].recReserve->GetPtr(); } } @@ -277,11 +279,11 @@ _vifT __fi void dVifUnpack(const u8* data, bool isFill) { if (dVifExecuteUnpack(data, isFill)) return; - xSetPtr(v.recPtr); + xSetPtr(v.recWritePtr); _vBlock.startPtr = (uptr)xGetAlignedCallTarget(); v.vifBlocks->add(_vBlock); VifUnpackSSE_Dynarec( v, _vBlock ).CompileRoutine(); - nVif[idx].recPtr = xGetPtr(); + nVif[idx].recWritePtr = xGetPtr(); // [TODO] : Ideally we should test recompile buffer limits prior to each instruction, // which would be safer and more memory efficient than using an 0.25 meg recEnd marker. diff --git a/pcsx2/x86/newVif_Unpack.cpp b/pcsx2/x86/newVif_Unpack.cpp index 0c692292c9..02808d152f 100644 --- a/pcsx2/x86/newVif_Unpack.cpp +++ b/pcsx2/x86/newVif_Unpack.cpp @@ -70,6 +70,19 @@ static const __aligned16 Fnptr_VifUnpackLoop UnpackLoopTable[2][2][2] = { }; // ---------------------------------------------------------------------------- +nVifStruct::nVifStruct() +{ + vifBlocks = NULL; + numBlocks = 0; + + recReserveSizeMB = 8; +} + +void reserveNewVif(int idx) +{ + if (newVifDynaRec) dVifReserve(idx); +} + void resetNewVif(int idx) { // Safety Reset : Reassign all VIF structure info, just in case the VU1 pointers have @@ -86,6 +99,10 @@ void closeNewVif(int idx) { if (newVifDynaRec) dVifClose(idx); } +void releaseNewVif(int idx) { + if (newVifDynaRec) dVifRelease(idx); +} + static __fi u8* getVUptr(uint idx, int offset) { return (u8*)(vuRegs[idx].Mem + ( offset & (idx ? 0x3ff0 : 0xff0) )); }