gsdx sw: sync thread if current target pages are already used by input texture

Otherwise you have a write before read typical race condition. It works
most of the time because textures are stored in temporary buffers (aka
texture cache). So the race condition requires texture invalidation in the mix.

I hope the perf impact will be small enough.

Fix #1691
Blood Will Tell: gray scale effect description

Frame is renderer in 0x700
Sync 0x700 (RT will be used as input)

Foreach page of frame
    // The missing Sync was this one. You can't copy new data to 0x2800
    // until you finish the rendering that use 0x2800 as input texture
    // (AKA end of this foreach loop)
    Sync 0x2800 (not the first iteration, texture will be used as a RT)
    Copy page from 0x700+offset to 0x2800

    Sync 0x2800 (RT will be used as input)
    Render Effect line1 from 0x2800 to 0x700
This commit is contained in:
Gregory Hainaut 2017-03-12 23:22:45 +01:00
parent 559f64ee4f
commit 1a768ca438
1 changed files with 7 additions and 5 deletions

View File

@ -756,7 +756,7 @@ void GSRendererSW::ReleasePages(const uint32* pages, const int type)
bool GSRendererSW::CheckTargetPages(const uint32* fb_pages, const uint32* zb_pages, const GSVector4i& r)
{
bool synced = m_rl->IsSynced();
bool fb = fb_pages != NULL;
bool zb = zb_pages != NULL;
@ -782,22 +782,24 @@ bool GSRendererSW::CheckTargetPages(const uint32* fb_pages, const uint32* zb_pag
uint32 row = i >> 5;
uint32 col = 1 << (i & 31);
m_fzb_cur_pages[row] |= col;
used |= m_fzb_pages[i];
used |= m_tex_pages[i];
}
for(const uint32* p = zb_pages; *p != GSOffset::EOP; p++)
{
uint32 i = *p;
uint32 row = i >> 5;
uint32 col = 1 << (i & 31);
m_fzb_cur_pages[row] |= col;
used |= m_fzb_pages[i];
used |= m_tex_pages[i];
}
if(!synced)
@ -921,7 +923,7 @@ bool GSRendererSW::CheckSourcePages(SharedData* sd)
{
for(size_t i = 0; sd->m_tex[i].t != NULL; i++)
{
sd->m_tex[i].t->m_offset->GetPages(sd->m_tex[i].r, m_tmp_pages);
sd->m_tex[i].t->m_offset->GetPages(sd->m_tex[i].r, m_tmp_pages);
uint32* pages = m_tmp_pages; // sd->m_tex[i].t->m_pages.n;