GSdx: Valkyrie Profile 2 fix (discussed under r5010 and r5012), this bug could have broken much more games, strange that it did not.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5015 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
gabest11 2011-12-24 15:02:48 +00:00
parent fa5fcf47de
commit ed8eb53c22
2 changed files with 54 additions and 26 deletions

View File

@ -304,7 +304,17 @@ void GSRendererSW::Sync(int reason)
m_rl->Sync(); m_rl->Sync();
memset(m_fzb_pages, 0, sizeof(m_fzb_pages)); // NOTE: m_fzb_pages is refcounted, zeroing is done automatically
#ifdef _DEBUG
for(size_t i = 0; i < countof(m_fzb_pages); i++)
{
ASSERT(m_fzb_pages[i] == 0);
}
#endif
memset(m_tex_pages, 0, sizeof(m_tex_pages)); memset(m_tex_pages, 0, sizeof(m_tex_pages));
} }
@ -366,6 +376,8 @@ void GSRendererSW::ReleaseTargetPages(GSOffset* o, const GSVector4i& rect)
for(list<uint32>::iterator i = pages->begin(); i != pages->end(); i++) for(list<uint32>::iterator i = pages->begin(); i != pages->end(); i++)
{ {
ASSERT(m_fzb_pages[*i] > 0);
_InterlockedDecrement(&m_fzb_pages[*i]); _InterlockedDecrement(&m_fzb_pages[*i]);
} }
} }
@ -374,12 +386,10 @@ void GSRendererSW::UseSourcePages(const GSTextureCacheSW::Texture* t)
{ {
for(list<uint32>::const_iterator i = t->m_pages.n.begin(); i != t->m_pages.n.end(); i++) for(list<uint32>::const_iterator i = t->m_pages.n.begin(); i != t->m_pages.n.end(); i++)
{ {
if(m_fzb_pages[*i]) // currently being drawn to? => sync if(m_fzb_pages[*i]) // currently being drawn to? => sync (could even spin and wait until it hits 0, not sure if it's worth though, or just create 512 condvars? :D)
{ {
//
Sync(7); Sync(7);
//
return; return;
} }
@ -518,7 +528,7 @@ bool GSRendererSW::GetScanlineGlobalData(GSScanlineGlobalData& gd)
string s; string s;
if(s_save && s_n >= s_saven && PRIM->TME) if(s_save && s_n >= s_saven)
{ {
s = format("c:\\temp1\\_%05d_f%lld_tex32_%05x_%d.bmp", s_n, frame, (int)m_context->TEX0.TBP0, (int)m_context->TEX0.PSM); s = format("c:\\temp1\\_%05d_f%lld_tex32_%05x_%d.bmp", s_n, frame, (int)m_context->TEX0.TBP0, (int)m_context->TEX0.PSM);

View File

@ -166,7 +166,7 @@ protected:
int m_count; int m_count;
queue<T> m_queue; queue<T> m_queue;
volatile bool m_exit; volatile bool m_exit;
struct {GSCritSec lock; GSEvent notempty, empty;} m_ev; struct {GSCritSec lock; GSEvent notempty; volatile long count;} m_ev;
#ifdef _WINDOWS #ifdef _WINDOWS
struct {SRWLOCK lock; CONDITION_VARIABLE notempty, empty; bool available;} m_cv; struct {SRWLOCK lock; CONDITION_VARIABLE notempty, empty; bool available;} m_cv;
HMODULE m_kernel32; HMODULE m_kernel32;
@ -203,6 +203,9 @@ protected:
if(m_exit) {pReleaseSRWLockExclusive(&m_cv.lock); return;} if(m_exit) {pReleaseSRWLockExclusive(&m_cv.lock); return;}
} }
{
// NOTE: this is scoped because we must make sure the last "item" is no longer around when Wait detects an empty queue
T item = m_queue.front(); T item = m_queue.front();
pReleaseSRWLockExclusive(&m_cv.lock); pReleaseSRWLockExclusive(&m_cv.lock);
@ -212,6 +215,7 @@ protected:
pAcquireSRWLockExclusive(&m_cv.lock); pAcquireSRWLockExclusive(&m_cv.lock);
m_queue.pop(); m_queue.pop();
}
if(m_queue.empty()) if(m_queue.empty())
{ {
@ -224,28 +228,36 @@ protected:
#endif #endif
while(m_ev.notempty.Wait()) m_ev.lock.Lock();
{
if(m_exit) break;
while(!m_queue.empty()) while(true)
{ {
T item; while(m_queue.empty())
{ {
GSAutoLock l(&m_ev.lock); m_ev.lock.Unlock();
item = m_queue.front(); m_ev.notempty.Wait();
if(m_exit) {return;}
m_ev.lock.Lock();
} }
{
// NOTE: this is scoped because we must make sure the last item is no longer around when Wait detects an empty queue
T item = m_queue.front();
m_ev.lock.Unlock();
Process(item); Process(item);
{ m_ev.lock.Lock();
GSAutoLock l(&m_ev.lock);
m_queue.pop(); m_queue.pop();
} }
}
_InterlockedDecrement(&m_ev.count);
} }
#ifdef _WINDOWS #ifdef _WINDOWS
@ -260,6 +272,8 @@ public:
: m_count(0) : m_count(0)
, m_exit(false) , m_exit(false)
{ {
m_ev.count = 0;
#ifdef _WINDOWS #ifdef _WINDOWS
m_cv.available = false; m_cv.available = false;
@ -345,6 +359,8 @@ public:
m_queue.push(item); m_queue.push(item);
_InterlockedIncrement(&m_ev.count);
m_ev.notempty.Set(); m_ev.notempty.Set();
#ifdef _WINDOWS #ifdef _WINDOWS
@ -376,7 +392,9 @@ public:
#endif #endif
while(!m_queue.empty()) _mm_pause(); // NOTE: it is the safest to have our own counter because m_queue.pop() might decrement its own before the last item runs out of its scope and gets destroyed (implementation dependent)
while(m_ev.count > 0) _mm_pause();
#ifdef _WINDOWS #ifdef _WINDOWS