mirror of https://github.com/PCSX2/pcsx2.git
GSdx: silent hill shattered memories purple street light fix, not block aligned filled rects were not correctly masked, may also fix games which store texture data in the alpha channel but use 24-bit target buffers (or just mask it in every time) and draw a lot of those unaligned rects. (tested many .gs dumps, very rare combination)
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5084 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
915a57d9f3
commit
bd12a8b7b3
|
@ -1492,6 +1492,7 @@ void GSDrawScanline::DrawRectT(const int* RESTRICT row, const int* RESTRICT col,
|
|||
if(masked) ASSERT(mask.u32[0] != 0);
|
||||
|
||||
color = color.andnot(mask);
|
||||
c = color.extract32<0>();
|
||||
|
||||
GSVector4i br = r.ralign<Align_Inside>(GSVector2i(8 * 4 / sizeof(T), 8));
|
||||
|
||||
|
|
|
@ -338,6 +338,8 @@ void GSRendererSW::ConvertVertexBuffer(GSVertexSW* RESTRICT dst, const GSVertex*
|
|||
|
||||
void GSRendererSW::Draw()
|
||||
{
|
||||
const GSDrawingContext* context = m_context;
|
||||
|
||||
SharedData* sd = new SharedData(this);
|
||||
|
||||
shared_ptr<GSRasterizerData> data(sd);
|
||||
|
@ -353,16 +355,11 @@ void GSRendererSW::Draw()
|
|||
|
||||
memcpy(sd->index, m_index.buff, sizeof(uint32) * m_index.tail);
|
||||
|
||||
if(!GetScanlineGlobalData(sd)) return;
|
||||
|
||||
//
|
||||
|
||||
const GSDrawingContext* context = m_context;
|
||||
|
||||
GSScanlineGlobalData& gd = sd->global;
|
||||
if(!GetScanlineGlobalData(sd)) return;
|
||||
|
||||
GSVector4i scissor = GSVector4i(context->scissor.in);
|
||||
GSVector4i bbox = GSVector4i(m_vt.m_min.p.floor().xyxy(m_vt.m_max.p.ceil()));
|
||||
GSVector4i r = bbox.rintersect(scissor);
|
||||
|
||||
scissor.z = std::min<int>(scissor.z, (int)context->FRAME.FBW * 64); // TODO: find a game that overflows and check which one is the right behaviour
|
||||
|
||||
|
@ -370,7 +367,42 @@ void GSRendererSW::Draw()
|
|||
sd->bbox = bbox;
|
||||
sd->frame = m_perfmon.GetFrame();
|
||||
|
||||
CheckDependencies(sd);
|
||||
//
|
||||
|
||||
GSScanlineGlobalData& gd = sd->global;
|
||||
|
||||
uint32* fb_pages = NULL;
|
||||
uint32* zb_pages = NULL;
|
||||
|
||||
if(sd->global.sel.fb)
|
||||
{
|
||||
fb_pages = m_context->offset.fb->GetPages(r);
|
||||
}
|
||||
|
||||
if(sd->global.sel.zb)
|
||||
{
|
||||
zb_pages = m_context->offset.zb->GetPages(r);
|
||||
}
|
||||
|
||||
// check if there is an overlap between this and previous targets
|
||||
|
||||
if(CheckTargetPages(fb_pages, zb_pages, r))
|
||||
{
|
||||
sd->m_syncpoint = SharedData::SyncTarget;
|
||||
}
|
||||
|
||||
// check if the texture is not part of a target currently in use
|
||||
|
||||
if(CheckSourcePages(sd))
|
||||
{
|
||||
sd->m_syncpoint = SharedData::SyncSource;
|
||||
}
|
||||
|
||||
// addref source and target pages
|
||||
|
||||
sd->UsePages(fb_pages, m_context->offset.fb->psm, zb_pages, m_context->offset.zb->psm);
|
||||
|
||||
//
|
||||
|
||||
if(LOG) {fprintf(s_fp, "queue %05x %d (%d) %05x %d (%d) %05x %d %dx%d | %d %d %d\n",
|
||||
m_context->FRAME.Block(), m_context->FRAME.PSM, gd.sel.fwrite,
|
||||
|
@ -411,7 +443,7 @@ void GSRendererSW::Draw()
|
|||
|
||||
s_n++;
|
||||
|
||||
m_rl->Queue(data);
|
||||
Queue(data);
|
||||
|
||||
Sync(4);
|
||||
|
||||
|
@ -433,7 +465,7 @@ void GSRendererSW::Draw()
|
|||
}
|
||||
else
|
||||
{
|
||||
m_rl->Queue(data);
|
||||
Queue(data);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -448,6 +480,39 @@ void GSRendererSW::Draw()
|
|||
*/
|
||||
}
|
||||
|
||||
void GSRendererSW::Queue(shared_ptr<GSRasterizerData>& item)
|
||||
{
|
||||
SharedData* sd = (SharedData*)item.get();
|
||||
|
||||
if(sd->m_syncpoint == SharedData::SyncSource)
|
||||
{
|
||||
m_rl->Sync();
|
||||
}
|
||||
|
||||
// update previously invalidated parts
|
||||
|
||||
sd->UpdateSource();
|
||||
|
||||
// invalidate new parts rendered onto
|
||||
|
||||
if(sd->global.sel.fwrite)
|
||||
{
|
||||
m_tc->InvalidatePages(sd->m_fb_pages, sd->m_fpsm);
|
||||
}
|
||||
|
||||
if(sd->global.sel.zwrite)
|
||||
{
|
||||
m_tc->InvalidatePages(sd->m_zb_pages, sd->m_zpsm);
|
||||
}
|
||||
|
||||
if(sd->m_syncpoint == SharedData::SyncTarget)
|
||||
{
|
||||
m_rl->Sync();
|
||||
}
|
||||
|
||||
m_rl->Queue(item);
|
||||
}
|
||||
|
||||
void GSRendererSW::Sync(int reason)
|
||||
{
|
||||
//printf("sync %d\n", reason);
|
||||
|
@ -580,71 +645,6 @@ void GSRendererSW::ReleasePages(const uint32* pages, int type)
|
|||
}
|
||||
}
|
||||
|
||||
void GSRendererSW::CheckDependencies(SharedData* sd)
|
||||
{
|
||||
GSVector4i r = sd->bbox.rintersect(sd->scissor);
|
||||
|
||||
uint32* fb_pages = NULL;
|
||||
uint32* zb_pages = NULL;
|
||||
|
||||
if(sd->global.sel.fb)
|
||||
{
|
||||
fb_pages = m_context->offset.fb->GetPages(r);
|
||||
}
|
||||
|
||||
if(sd->global.sel.zb)
|
||||
{
|
||||
zb_pages = m_context->offset.zb->GetPages(r);
|
||||
}
|
||||
|
||||
// check if there is an overlap between this and previous targets
|
||||
|
||||
bool target_syncpoint = false;
|
||||
|
||||
if(CheckTargetPages(fb_pages, zb_pages, r))
|
||||
{
|
||||
target_syncpoint = true;
|
||||
}
|
||||
|
||||
// check if the texture is not part of a target currently in use
|
||||
|
||||
bool source_syncpoint = false;
|
||||
|
||||
if(CheckSourcePages(sd))
|
||||
{
|
||||
source_syncpoint = true;
|
||||
target_syncpoint = false;
|
||||
}
|
||||
|
||||
// addref target pages
|
||||
|
||||
sd->UseTargetPages(fb_pages, zb_pages);
|
||||
|
||||
// addref texture pages and update previously invalidated parts
|
||||
|
||||
if(source_syncpoint)
|
||||
{
|
||||
Sync(8);
|
||||
}
|
||||
|
||||
sd->UseSourcePages();
|
||||
|
||||
if(sd->global.sel.fwrite)
|
||||
{
|
||||
m_tc->InvalidatePages(fb_pages, m_context->offset.fb->psm);
|
||||
}
|
||||
|
||||
if(sd->global.sel.zwrite)
|
||||
{
|
||||
m_tc->InvalidatePages(zb_pages, m_context->offset.zb->psm);
|
||||
}
|
||||
|
||||
if(target_syncpoint)
|
||||
{
|
||||
Sync(9);
|
||||
}
|
||||
}
|
||||
|
||||
bool GSRendererSW::CheckTargetPages(const uint32* fb_pages, const uint32* zb_pages, const GSVector4i& r)
|
||||
{
|
||||
bool synced = m_rl->IsSynced();
|
||||
|
@ -1313,6 +1313,7 @@ GSRendererSW::SharedData::SharedData(GSRendererSW* parent)
|
|||
, m_fb_pages(NULL)
|
||||
, m_zb_pages(NULL)
|
||||
, m_using_pages(false)
|
||||
, m_syncpoint(SyncNone)
|
||||
{
|
||||
m_tex[0].t = NULL;
|
||||
|
||||
|
@ -1324,38 +1325,16 @@ GSRendererSW::SharedData::SharedData(GSRendererSW* parent)
|
|||
|
||||
GSRendererSW::SharedData::~SharedData()
|
||||
{
|
||||
if(m_using_pages)
|
||||
{
|
||||
if(global.sel.fb)
|
||||
{
|
||||
m_parent->ReleasePages(m_fb_pages, 0);
|
||||
}
|
||||
ReleasePages();
|
||||
|
||||
if(global.sel.zb)
|
||||
{
|
||||
m_parent->ReleasePages(m_zb_pages, 1);
|
||||
}
|
||||
}
|
||||
|
||||
delete [] m_fb_pages;
|
||||
delete [] m_zb_pages;
|
||||
|
||||
for(size_t i = 0; m_tex[i].t != NULL; i++)
|
||||
{
|
||||
m_parent->ReleasePages(m_tex[i].t->m_pages.n, 2);
|
||||
}
|
||||
|
||||
if(global.clut) _aligned_free(global.clut);
|
||||
if(global.dimx) _aligned_free(global.dimx);
|
||||
}
|
||||
|
||||
void GSRendererSW::SharedData::UseTargetPages(const uint32* fb_pages, const uint32* zb_pages)
|
||||
void GSRendererSW::SharedData::UsePages(const uint32* fb_pages, int fpsm, const uint32* zb_pages, int zpsm)
|
||||
{
|
||||
if(m_using_pages) return;
|
||||
|
||||
m_fb_pages = fb_pages;
|
||||
m_zb_pages = zb_pages;
|
||||
|
||||
if(global.sel.fb)
|
||||
{
|
||||
m_parent->UsePages(fb_pages, 0);
|
||||
|
@ -1366,9 +1345,47 @@ void GSRendererSW::SharedData::UseTargetPages(const uint32* fb_pages, const uint
|
|||
m_parent->UsePages(zb_pages, 1);
|
||||
}
|
||||
|
||||
for(size_t i = 0; m_tex[i].t != NULL; i++)
|
||||
{
|
||||
m_parent->UsePages(m_tex[i].t->m_pages.n, 2);
|
||||
}
|
||||
|
||||
m_fb_pages = fb_pages;
|
||||
m_zb_pages = zb_pages;
|
||||
m_fpsm = fpsm;
|
||||
m_zpsm = zpsm;
|
||||
|
||||
m_using_pages = true;
|
||||
}
|
||||
|
||||
void GSRendererSW::SharedData::ReleasePages()
|
||||
{
|
||||
if(!m_using_pages) return;
|
||||
|
||||
if(global.sel.fb)
|
||||
{
|
||||
m_parent->ReleasePages(m_fb_pages, 0);
|
||||
}
|
||||
|
||||
if(global.sel.zb)
|
||||
{
|
||||
m_parent->ReleasePages(m_zb_pages, 1);
|
||||
}
|
||||
|
||||
for(size_t i = 0; m_tex[i].t != NULL; i++)
|
||||
{
|
||||
m_parent->ReleasePages(m_tex[i].t->m_pages.n, 2);
|
||||
}
|
||||
|
||||
delete [] m_fb_pages;
|
||||
delete [] m_zb_pages;
|
||||
|
||||
m_fb_pages = NULL;
|
||||
m_zb_pages = NULL;
|
||||
|
||||
m_using_pages = false;
|
||||
}
|
||||
|
||||
void GSRendererSW::SharedData::SetSource(GSTextureCacheSW::Texture* t, const GSVector4i& r, int level)
|
||||
{
|
||||
ASSERT(m_tex[level].t == NULL);
|
||||
|
@ -1379,12 +1396,10 @@ void GSRendererSW::SharedData::SetSource(GSTextureCacheSW::Texture* t, const GSV
|
|||
m_tex[level + 1].t = NULL;
|
||||
}
|
||||
|
||||
void GSRendererSW::SharedData::UseSourcePages()
|
||||
void GSRendererSW::SharedData::UpdateSource()
|
||||
{
|
||||
for(size_t i = 0; m_tex[i].t != NULL; i++)
|
||||
{
|
||||
m_parent->UsePages(m_tex[i].t->m_pages.n, 2);
|
||||
|
||||
if(m_tex[i].t->Update(m_tex[i].r))
|
||||
{
|
||||
global.tex[i] = m_tex[i].t->m_buff;
|
||||
|
|
|
@ -29,21 +29,31 @@ class GSRendererSW : public GSRenderer
|
|||
{
|
||||
class SharedData : public GSDrawScanline::SharedData
|
||||
{
|
||||
__aligned(struct, 16) TextureLevel
|
||||
{
|
||||
GSVector4i r;
|
||||
GSTextureCacheSW::Texture* t;
|
||||
};
|
||||
|
||||
public:
|
||||
GSRendererSW* m_parent;
|
||||
const uint32* m_fb_pages;
|
||||
const uint32* m_zb_pages;
|
||||
int m_fpsm;
|
||||
int m_zpsm;
|
||||
bool m_using_pages;
|
||||
__aligned(struct, 16) {GSVector4i r; GSTextureCacheSW::Texture* t;} m_tex[7 + 1]; // NULL terminated
|
||||
TextureLevel m_tex[7 + 1]; // NULL terminated
|
||||
enum {SyncNone, SyncSource, SyncTarget} m_syncpoint;
|
||||
|
||||
public:
|
||||
SharedData(GSRendererSW* parent);
|
||||
virtual ~SharedData();
|
||||
|
||||
void UseTargetPages(const uint32* fb_pages, const uint32* zb_pages);
|
||||
void UsePages(const uint32* fb_pages, int fpsm, const uint32* zb_pages, int zpsm);
|
||||
void ReleasePages();
|
||||
|
||||
void SetSource(GSTextureCacheSW::Texture* t, const GSVector4i& r, int level);
|
||||
void UseSourcePages();
|
||||
void UpdateSource();
|
||||
};
|
||||
|
||||
typedef void (GSRendererSW::*ConvertVertexBufferPtr)(GSVertexSW* RESTRICT dst, const GSVertex* RESTRICT src, size_t count);
|
||||
|
@ -71,6 +81,7 @@ protected:
|
|||
GSTexture* GetOutput(int i);
|
||||
|
||||
void Draw();
|
||||
void Queue(shared_ptr<GSRasterizerData>& item);
|
||||
void Sync(int reason);
|
||||
void InvalidateVideoMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r);
|
||||
void InvalidateLocalMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r, bool clut = false);
|
||||
|
@ -78,7 +89,6 @@ protected:
|
|||
void UsePages(const uint32* pages, int type);
|
||||
void ReleasePages(const uint32* pages, int type);
|
||||
|
||||
void CheckDependencies(SharedData* sd);
|
||||
bool CheckTargetPages(const uint32* fb_pages, const uint32* zb_pages, const GSVector4i& r);
|
||||
bool CheckSourcePages(SharedData* sd);
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ cbuffer PSConstantBuffer : register(c0)
|
|||
|
||||
struct FragmentLinkItem
|
||||
{
|
||||
uint c, z, id, next;
|
||||
uint c, z, id, next;
|
||||
};
|
||||
|
||||
RWByteAddressBuffer VideoMemory : register(u0);
|
||||
|
@ -146,9 +146,9 @@ void gs_main(line VS_OUTPUT input[2], inout LineStream<GS_OUTPUT> stream, uint i
|
|||
output.c = input[i].c;
|
||||
output.id = id;
|
||||
|
||||
#if GS_IIP == 0
|
||||
#if GS_IIP == 0
|
||||
if(i != 1) output.c = input[1].c;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
stream.Append(output);
|
||||
}
|
||||
|
@ -170,9 +170,9 @@ void gs_main(triangle VS_OUTPUT input[3], inout TriangleStream<GS_OUTPUT> stream
|
|||
output.c = input[i].c;
|
||||
output.id = id;
|
||||
|
||||
#if GS_IIP == 0
|
||||
#if GS_IIP == 0
|
||||
if(i != 2) output.c = input[2].c;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
stream.Append(output);
|
||||
}
|
||||
|
@ -192,9 +192,9 @@ void gs_main(line VS_OUTPUT input[2], inout TriangleStream<GS_OUTPUT> stream, ui
|
|||
lt.c = input[0].c;
|
||||
lt.id = id;
|
||||
|
||||
#if GS_IIP == 0
|
||||
#if GS_IIP == 0
|
||||
lt.c = input[1].c;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
rb.p = input[1].p;
|
||||
rb.z = input[1].z;
|
||||
|
@ -268,23 +268,23 @@ void ps_main0(GS_OUTPUT input)
|
|||
uint x = (uint)input.p.x;
|
||||
uint y = (uint)input.p.y;
|
||||
|
||||
uint tail = FragmentLinkBuffer.IncrementCounter();
|
||||
uint tail = FragmentLinkBuffer.IncrementCounter();
|
||||
|
||||
uint index = (y << 11) + x;
|
||||
uint index = (y << 11) + x;
|
||||
uint next = 0;
|
||||
|
||||
StartOffsetBuffer.InterlockedExchange(index * 4, tail, next);
|
||||
|
||||
FragmentLinkItem item;
|
||||
|
||||
FragmentLinkItem item;
|
||||
|
||||
// TODO: preprocess color (tfx, alpha test), z-test
|
||||
|
||||
item.c = CompressColor32(input.c);
|
||||
item.z = (uint)(input.z.y * 0x10000 + input.z.x);
|
||||
item.id = input.id;
|
||||
item.next = next;
|
||||
item.next = next;
|
||||
|
||||
FragmentLinkBuffer[tail] = item;
|
||||
FragmentLinkBuffer[tail] = item;
|
||||
}
|
||||
|
||||
void ps_main1(GS_OUTPUT input)
|
||||
|
@ -293,7 +293,7 @@ void ps_main1(GS_OUTPUT input)
|
|||
|
||||
// sort fragments
|
||||
|
||||
uint StartOffsetIndex = (pos.y << 11) + pos.x;
|
||||
uint StartOffsetIndex = (pos.y << 11) + pos.x;
|
||||
|
||||
int index[PS_BATCH_SIZE];
|
||||
int count = 0;
|
||||
|
@ -303,7 +303,7 @@ void ps_main1(GS_OUTPUT input)
|
|||
StartOffsetBuffer.Store(StartOffsetIndex * 4, 0);
|
||||
|
||||
[allow_uav_condition]
|
||||
while(next != 0)
|
||||
while(next != 0)
|
||||
{
|
||||
index[count++] = next;
|
||||
|
||||
|
@ -313,8 +313,8 @@ void ps_main1(GS_OUTPUT input)
|
|||
int N2 = 1 << (int)(ceil(log2(count)));
|
||||
|
||||
[allow_uav_condition]
|
||||
for(int i = count; i < N2; i++)
|
||||
{
|
||||
for(int i = count; i < N2; i++)
|
||||
{
|
||||
index[i] = 0;
|
||||
}
|
||||
|
||||
|
@ -330,7 +330,7 @@ void ps_main1(GS_OUTPUT input)
|
|||
uint i_id = FragmentLinkBuffer[index[i]].id;
|
||||
|
||||
int ixj = i ^ j;
|
||||
|
||||
|
||||
if(ixj > i)
|
||||
{
|
||||
uint ixj_id = FragmentLinkBuffer[index[ixj]].id;
|
||||
|
@ -363,7 +363,7 @@ void ps_main1(GS_OUTPUT input)
|
|||
|
||||
[allow_uav_condition]
|
||||
while(--count >= 0)
|
||||
{
|
||||
{
|
||||
FragmentLinkItem f = FragmentLinkBuffer[index[count]];
|
||||
|
||||
// TODO
|
||||
|
@ -374,7 +374,7 @@ void ps_main1(GS_OUTPUT input)
|
|||
sz = f.z;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint c = sc; // (dc & ~WriteMask.x) | (sc & WriteMask.x);
|
||||
uint z = 0;//sz; //(dz & ~WriteMask.y) | (sz & WriteMask.y);
|
||||
|
||||
|
|
Loading…
Reference in New Issue