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,15 +386,13 @@ 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;
} }
} }
for(size_t i = 0; i < countof(t->m_pages.bm); i++) for(size_t i = 0; i < countof(t->m_pages.bm); i++)
@ -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,15 +203,19 @@ protected:
if(m_exit) {pReleaseSRWLockExclusive(&m_cv.lock); return;} if(m_exit) {pReleaseSRWLockExclusive(&m_cv.lock); return;}
} }
T item = m_queue.front(); {
// NOTE: this is scoped because we must make sure the last "item" is no longer around when Wait detects an empty queue
pReleaseSRWLockExclusive(&m_cv.lock); T item = m_queue.front();
Process(item); pReleaseSRWLockExclusive(&m_cv.lock);
pAcquireSRWLockExclusive(&m_cv.lock); Process(item);
m_queue.pop(); pAcquireSRWLockExclusive(&m_cv.lock);
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();
while(true)
{ {
if(m_exit) break; while(m_queue.empty())
while(!m_queue.empty())
{ {
T item; m_ev.lock.Unlock();
{ m_ev.notempty.Wait();
GSAutoLock l(&m_ev.lock);
item = m_queue.front(); 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
@ -375,8 +391,10 @@ public:
{ {
#endif #endif
// 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_queue.empty()) _mm_pause(); while(m_ev.count > 0) _mm_pause();
#ifdef _WINDOWS #ifdef _WINDOWS