From 20cd5e9b81f75fd0c20896506f36ad12894a1b53 Mon Sep 17 00:00:00 2001 From: gabest11 Date: Sat, 21 Jan 2012 12:34:36 +0000 Subject: [PATCH] GSdx: next attempt to fix frame skipping git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5078 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GS.h | 50 ++++++++++++++++++++++++++++---- plugins/GSdx/GSRendererSW.cpp | 46 ++++++++++++++++++++++------- plugins/GSdx/GSState.cpp | 53 ++++++++++++++++++++++++++++++++++ plugins/GSdx/GSState.h | 4 ++- plugins/GSdx/GSVertexTrace.cpp | 10 +++++++ 5 files changed, 147 insertions(+), 16 deletions(-) diff --git a/plugins/GSdx/GS.h b/plugins/GSdx/GS.h index a39a5dcd83..a501cbc2fe 100644 --- a/plugins/GSdx/GS.h +++ b/plugins/GSdx/GS.h @@ -92,7 +92,8 @@ enum GIF_REG enum GIF_REG_COMPLEX { - GIF_REG_STQRGBAXYZF2 = 0x00, + GIF_REG_STQRGBAXYZF2 = 0x00, + GIF_REG_STQRGBAXYZ2 = 0x01, }; enum GIF_A_D_REG @@ -1101,19 +1102,58 @@ __aligned(struct, 32) GIFPath uint32 type; GSVector4i regs; - enum {TYPE_UNKNOWN, TYPE_ADONLY, TYPE_STQRGBAXYZF2}; + enum {TYPE_UNKNOWN, TYPE_ADONLY, TYPE_STQRGBAXYZF2, TYPE_STQRGBAXYZ2}; __forceinline void SetTag(const void* mem) { GSVector4i v = GSVector4i::load(mem); GSVector4i::store(&tag, v); + reg = 0; nreg = tag.NREG ? tag.NREG : 16; regs = v.uph8(v >> 4) & GSVector4i::x0f(nreg); nloop = tag.NLOOP; - if(regs.u32[0] == 0x00040102 && nreg == 3) type = TYPE_STQRGBAXYZF2; - else if(regs.eq8(GSVector4i(0x0e0e0e0e)).mask() == (1 << nreg) - 1) type = TYPE_ADONLY; - else type = TYPE_UNKNOWN; + type = TYPE_UNKNOWN; + + if(tag.FLG == GIF_FLG_PACKED) + { + if(regs.eq8(GSVector4i(0x0e0e0e0e)).mask() == (1 << nreg) - 1) + { + type = TYPE_ADONLY; + } + else + { + switch(nreg) + { + case 1: break; + case 2: break; + case 3: + if(regs.u32[0] == 0x00040102) type = TYPE_STQRGBAXYZF2; // many games, TODO: formats mixed with NOPs (xeno2: 040f010f02, 04010f020f, mgs3: 04010f0f02, 0401020f0f, 04010f020f) + if(regs.u32[0] == 0x00050102) type = TYPE_STQRGBAXYZ2; // GoW (has other crazy formats, like ...030503050103) + // TODO: common types with UV instead + break; + case 4: break; + case 5: break; + case 6: break; + case 7: break; + case 8: break; + case 9: + if(regs.u32[0] == 0x02040102 && regs.u32[1] == 0x01020401 && regs.u32[2] == 0x00000004) {type = TYPE_STQRGBAXYZF2; nreg = 3; nloop *= 3;} // ffx + break; + case 10: break; + case 11: break; + case 12: + if(regs.u32[0] == 0x02040102 && regs.u32[1] == 0x01020401 && regs.u32[2] == 0x04010204) {type = TYPE_STQRGBAXYZF2; nreg = 3; nloop *= 4;} // dq8 (not many, mostly 040102) + break; + case 13: break; + case 14: break; + case 15: break; + case 16: break; + default: + __assume(0); + } + } + } } __forceinline uint8 GetReg() diff --git a/plugins/GSdx/GSRendererSW.cpp b/plugins/GSdx/GSRendererSW.cpp index e90bdaaef4..db5d0f1d16 100644 --- a/plugins/GSdx/GSRendererSW.cpp +++ b/plugins/GSdx/GSRendererSW.cpp @@ -131,9 +131,28 @@ void GSRendererSW::VSync(int field) m_regs->PMODE.ALP ); - fprintf(s_fp, "SMODE1 %08x_%08x\n", - m_regs->SMODE1.u32[0], - m_regs->SMODE1.u32[1] + fprintf(s_fp, "SMODE1 CLKSEL=%d CMOD=%d EX=%d GCONT=%d LC=%d NVCK=%d PCK2=%d PEHS=%d PEVS=%d PHS=%d PRST=%d PVS=%d RC=%d SINT=%d SLCK=%d SLCK2=%d SPML=%d T1248=%d VCKSEL=%d VHP=%d XPCK=%d\n", + m_regs->SMODE1.CLKSEL, + m_regs->SMODE1.CMOD, + m_regs->SMODE1.EX, + m_regs->SMODE1.GCONT, + m_regs->SMODE1.LC, + m_regs->SMODE1.NVCK, + m_regs->SMODE1.PCK2, + m_regs->SMODE1.PEHS, + m_regs->SMODE1.PEVS, + m_regs->SMODE1.PHS, + m_regs->SMODE1.PRST, + m_regs->SMODE1.PVS, + m_regs->SMODE1.RC, + m_regs->SMODE1.SINT, + m_regs->SMODE1.SLCK, + m_regs->SMODE1.SLCK2, + m_regs->SMODE1.SPML, + m_regs->SMODE1.T1248, + m_regs->SMODE1.VCKSEL, + m_regs->SMODE1.VHP, + m_regs->SMODE1.XPCK ); fprintf(s_fp, "SMODE2 INT=%d FFMD=%d DPMS=%d\n", @@ -485,7 +504,7 @@ void GSRendererSW::InvalidateLocalMem(const GIFRegBITBLTBUF& BITBLTBUF, const GS { if(m_fzb_pages[*p]) { - Sync(6); + Sync(7); break; } @@ -581,7 +600,7 @@ void GSRendererSW::CheckDependencies(SharedData* sd) if(source_syncpoint) { - Sync(7); + Sync(8); } sd->UseSourcePages(); @@ -598,7 +617,7 @@ void GSRendererSW::CheckDependencies(SharedData* sd) if(target_syncpoint) { - Sync(8); + Sync(9); } } @@ -653,7 +672,7 @@ bool GSRendererSW::CheckTargetPages(const uint32* fb_pages, const uint32* zb_pag return true; } - if(LOG) {fprintf(s_fp, "no syncpoint *\n"); fflush(s_fp);} + //if(LOG) {fprintf(s_fp, "no syncpoint *\n"); fflush(s_fp);} } } else @@ -759,7 +778,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); - + uint32* pages = m_tmp_pages; // sd->m_tex[i].t->m_pages.n; for(const uint32* p = pages; *p != GSOffset::EOP; p++) @@ -1337,9 +1356,16 @@ void GSRendererSW::SharedData::UseSourcePages() { m_parent->UsePages(m_tex[i].t->m_pages.n, 2); - m_tex[i].t->Update(m_tex[i].r); // TODO: check return value, false (out-of-memory) then disable texturing + if(m_tex[i].t->Update(m_tex[i].r)) + { + global.tex[i] = m_tex[i].t->m_buff; + } + else + { + printf("GSdx: out-of-memory, texturing temporarily disabled\n"); - global.tex[i] = m_tex[i].t->m_buff; + global.sel.tfx = TFX_NONE; + } // TODO /* diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index 36797a113b..3c20cc5e80 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -166,6 +166,7 @@ void GSState::SetFrameSkip(int skip) m_fpGIFRegHandlers[GIF_A_D_REG_XYZ3] = &GSState::GIFRegHandlerNOP; m_fpGIFPackedRegHandlersC[GIF_REG_STQRGBAXYZF2] = &GSState::GIFPackedRegHandlerNOP; + m_fpGIFPackedRegHandlersC[GIF_REG_STQRGBAXYZ2] = &GSState::GIFPackedRegHandlerNOP; } else { @@ -223,6 +224,7 @@ void GSState::ResetHandlers() m_fpGIFRegHandlerXYZ[P][2] = &GSState::GIFRegHandlerXYZ2; \ m_fpGIFRegHandlerXYZ[P][3] = &GSState::GIFRegHandlerXYZ2; \ m_fpGIFPackedRegHandlerSTQRGBAXYZF2[P] = &GSState::GIFPackedRegHandlerSTQRGBAXYZF2

; \ + m_fpGIFPackedRegHandlerSTQRGBAXYZ2[P] = &GSState::GIFPackedRegHandlerSTQRGBAXYZ2

; \ SetHandlerXYZ(GS_POINTLIST); SetHandlerXYZ(GS_LINELIST); @@ -340,6 +342,8 @@ GSVector4i GSState::GetFrameRect(int i) GSVector2i GSState::GetDeviceSize(int i) { + // TODO: return (m_regs->SMODE1.CMOD & 1) ? GSVector2i(640, 576) : GSVector2i(640, 480); + // TODO: other params of SMODE1 should affect the true device display size // TODO2: pal games at 60Hz @@ -538,6 +542,33 @@ void GSState::GIFPackedRegHandlerSTQRGBAXYZF2(const GIFPackedReg* RESTRICT r, ui } } +template +void GSState::GIFPackedRegHandlerSTQRGBAXYZ2(const GIFPackedReg* RESTRICT r, uint32 size) +{ + ASSERT(size > 0 && size % 3 == 0); + + const GIFPackedReg* RESTRICT r_end = r + size; + + while(r < r_end) + { + GSVector4i st = GSVector4i::loadl(&r[0].u64[0]); + GSVector4i q = GSVector4i::loadl(&r[0].u64[1]); + GSVector4i rgba = (GSVector4i::load(&r[1]) & GSVector4i::x000000ff()).ps32().pu16(); + + m_v.m[0] = st.upl64(rgba.upl32(q)); // TODO: only store the last one + + GSVector4i xy = GSVector4i::loadl(&r[2].u64[0]); + GSVector4i z = GSVector4i::loadl(&r[2].u64[1]); + GSVector4i xyz = xy.upl16(xy.srl<4>()).upl32(z); + + m_v.m[1] = xyz.upl64(GSVector4i::loadl(&m_v.UV)); // TODO: only store the last one + + VertexKick(r[2].XYZ2.Skip()); + + r += 3; + } +} + void GSState::GIFPackedRegHandlerNOP(const GIFPackedReg* RESTRICT r, uint32 size) { } @@ -1633,6 +1664,8 @@ template void GSState::Transfer<1>(const uint8* mem, uint32 size); template void GSState::Transfer<2>(const uint8* mem, uint32 size); template void GSState::Transfer<3>(const uint8* mem, uint32 size); +static hash_map s_tags; + template void GSState::Transfer(const uint8* mem, uint32 size) { GSPerfMonAutoTimer pmat(&m_perfmon); @@ -1647,6 +1680,15 @@ template void GSState::Transfer(const uint8* mem, uint32 size) { path.SetTag(mem); + if(0) + { + uint64 hash; + if(path.tag.NREG < 8) hash = path.tag.u32[2] & ((1 << path.tag.NREG * 4) - 1); + else if(path.tag.NREG < 16) {hash = path.tag.u32[2]; ((uint32*)&hash)[1] = path.tag.u32[3] & ((1 << (path.tag.NREG - 8) * 4) - 1);} + else hash = path.tag.u64[1]; + s_tags[hash] += path.nloop * path.nreg; + } + mem += sizeof(GIFTag); size--; @@ -1734,6 +1776,14 @@ template void GSState::Transfer(const uint8* mem, uint32 size) break; + case GIFPath::TYPE_STQRGBAXYZ2: + + (this->*m_fpGIFPackedRegHandlersC[GIF_REG_STQRGBAXYZ2])((GIFPackedReg*)mem, total); + + mem += total * sizeof(GIFPackedReg); + + break; + default: __assume(0); @@ -2093,6 +2143,8 @@ void GSState::UpdateScissor() void GSState::UpdateVertexKick() { + if(m_frameskip) return; + uint32 prim = PRIM->PRIM; m_fpGIFPackedRegHandlers[GIF_REG_XYZF2] = m_fpGIFPackedRegHandlerXYZ[prim][0]; @@ -2106,6 +2158,7 @@ void GSState::UpdateVertexKick() m_fpGIFRegHandlers[GIF_A_D_REG_XYZ3] = m_fpGIFRegHandlerXYZ[prim][3]; m_fpGIFPackedRegHandlersC[GIF_REG_STQRGBAXYZF2] = m_fpGIFPackedRegHandlerSTQRGBAXYZF2[prim]; + m_fpGIFPackedRegHandlersC[GIF_REG_STQRGBAXYZ2] = m_fpGIFPackedRegHandlerSTQRGBAXYZ2[prim]; } void GSState::GrowVertexBuffer() diff --git a/plugins/GSdx/GSState.h b/plugins/GSdx/GSState.h index ad75f6a18e..94ed80d67f 100644 --- a/plugins/GSdx/GSState.h +++ b/plugins/GSdx/GSState.h @@ -61,10 +61,12 @@ class GSState : public GSAlignedClass<32> typedef void (GSState::*GIFPackedRegHandlerC)(const GIFPackedReg* RESTRICT r, uint32 size); - GIFPackedRegHandlerC m_fpGIFPackedRegHandlersC[1]; + GIFPackedRegHandlerC m_fpGIFPackedRegHandlersC[2]; GIFPackedRegHandlerC m_fpGIFPackedRegHandlerSTQRGBAXYZF2[8]; + GIFPackedRegHandlerC m_fpGIFPackedRegHandlerSTQRGBAXYZ2[8]; template void GIFPackedRegHandlerSTQRGBAXYZF2(const GIFPackedReg* RESTRICT r, uint32 size); + template void GIFPackedRegHandlerSTQRGBAXYZ2(const GIFPackedReg* RESTRICT r, uint32 size); void GIFPackedRegHandlerNOP(const GIFPackedReg* RESTRICT r, uint32 size); template void ApplyTEX0(GIFRegTEX0& TEX0); diff --git a/plugins/GSdx/GSVertexTrace.cpp b/plugins/GSdx/GSVertexTrace.cpp index 63f4c1a3bd..1d1ea056c9 100644 --- a/plugins/GSdx/GSVertexTrace.cpp +++ b/plugins/GSdx/GSVertexTrace.cpp @@ -225,10 +225,20 @@ void GSVertexTrace::FindMinMax(const void* vertex, const uint32* index, int coun m_min.t = tmin * s; m_max.t = tmax * s; } + else + { + m_min.t = GSVector4::zero(); + m_max.t = GSVector4::zero(); + } if(color) { m_min.c = cmin.zzzz().u8to32(); m_max.c = cmax.zzzz().u8to32(); } + else + { + m_min.c = GSVector4i::zero(); + m_max.c = GSVector4i::zero(); + } }