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