From 3784ea768f4be8441c7fe9e2d665229d336421f5 Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Tue, 4 Aug 2015 19:26:17 +0200 Subject: [PATCH 1/2] gsdx: check null pointer when doing a texture clear --- plugins/GSdx/GSDevice11.cpp | 4 ++++ plugins/GSdx/GSDevice9.cpp | 4 ++++ plugins/GSdx/GSDeviceOGL.cpp | 10 ++++++++++ plugins/GSdx/GSRendererDX.cpp | 4 ++-- plugins/GSdx/GSRendererOGL.cpp | 6 +++--- 5 files changed, 23 insertions(+), 5 deletions(-) diff --git a/plugins/GSdx/GSDevice11.cpp b/plugins/GSdx/GSDevice11.cpp index 24730e3225..a138507dcf 100644 --- a/plugins/GSdx/GSDevice11.cpp +++ b/plugins/GSdx/GSDevice11.cpp @@ -444,11 +444,13 @@ void GSDevice11::Dispatch(uint32 x, uint32 y, uint32 z) void GSDevice11::ClearRenderTarget(GSTexture* t, const GSVector4& c) { + if (!t) return; m_ctx->ClearRenderTargetView(*(GSTexture11*)t, c.v); } void GSDevice11::ClearRenderTarget(GSTexture* t, uint32 c) { + if (!t) return; GSVector4 color = GSVector4::rgba32(c) * (1.0f / 255); m_ctx->ClearRenderTargetView(*(GSTexture11*)t, color.v); @@ -456,11 +458,13 @@ void GSDevice11::ClearRenderTarget(GSTexture* t, uint32 c) void GSDevice11::ClearDepth(GSTexture* t, float c) { + if (!t) return; m_ctx->ClearDepthStencilView(*(GSTexture11*)t, D3D11_CLEAR_DEPTH, c, 0); } void GSDevice11::ClearStencil(GSTexture* t, uint8 c) { + if (!t) return; m_ctx->ClearDepthStencilView(*(GSTexture11*)t, D3D11_CLEAR_STENCIL, 0, c); } diff --git a/plugins/GSdx/GSDevice9.cpp b/plugins/GSdx/GSDevice9.cpp index 1b9f26599a..8d1c3cd629 100644 --- a/plugins/GSdx/GSDevice9.cpp +++ b/plugins/GSdx/GSDevice9.cpp @@ -649,11 +649,13 @@ void GSDevice9::EndScene() void GSDevice9::ClearRenderTarget(GSTexture* t, const GSVector4& c) { + if (!t) return; ClearRenderTarget(t, (c * 255 + 0.5f).zyxw().rgba32()); } void GSDevice9::ClearRenderTarget(GSTexture* rt, uint32 c) { + if (!rt) return; CComPtr surface; m_dev->GetRenderTarget(0, &surface); m_dev->SetRenderTarget(0, *(GSTexture9*)rt); @@ -663,6 +665,7 @@ void GSDevice9::ClearRenderTarget(GSTexture* rt, uint32 c) void GSDevice9::ClearDepth(GSTexture* t, float c) { + if (!t) return; CComPtr dssurface; m_dev->GetDepthStencilSurface(&dssurface); m_dev->SetDepthStencilSurface(*(GSTexture9*)t); @@ -672,6 +675,7 @@ void GSDevice9::ClearDepth(GSTexture* t, float c) void GSDevice9::ClearStencil(GSTexture* t, uint8 c) { + if (!t) return; CComPtr dssurface; m_dev->GetDepthStencilSurface(&dssurface); m_dev->SetDepthStencilSurface(*(GSTexture9*)t); diff --git a/plugins/GSdx/GSDeviceOGL.cpp b/plugins/GSdx/GSDeviceOGL.cpp index 417e03c80c..e1be2c1196 100644 --- a/plugins/GSdx/GSDeviceOGL.cpp +++ b/plugins/GSdx/GSDeviceOGL.cpp @@ -444,6 +444,8 @@ void GSDeviceOGL::DrawIndexedPrimitive(int offset, int count) void GSDeviceOGL::ClearRenderTarget(GSTexture* t, const GSVector4& c) { + if (!t) return; + GSTextureOGL* T = static_cast(t); if (T->HasBeenCleaned() && !T->IsBackbuffer()) return; @@ -481,12 +483,16 @@ void GSDeviceOGL::ClearRenderTarget(GSTexture* t, const GSVector4& c) void GSDeviceOGL::ClearRenderTarget(GSTexture* t, uint32 c) { + if (!t) return; + GSVector4 color = GSVector4::rgba32(c) * (1.0f / 255); ClearRenderTarget(t, color); } void GSDeviceOGL::ClearRenderTarget_i(GSTexture* t, int32 c) { + if (!t) return; + GSTextureOGL* T = static_cast(t); GL_PUSH("Clear RTi %d", T->GetID()); @@ -514,6 +520,8 @@ void GSDeviceOGL::ClearRenderTarget_i(GSTexture* t, int32 c) void GSDeviceOGL::ClearDepth(GSTexture* t, float c) { + if (!t) return; + GSTextureOGL* T = static_cast(t); GL_PUSH("Clear Depth %d", T->GetID()); @@ -537,6 +545,8 @@ void GSDeviceOGL::ClearDepth(GSTexture* t, float c) void GSDeviceOGL::ClearStencil(GSTexture* t, uint8 c) { + if (!t) return; + GSTextureOGL* T = static_cast(t); GL_PUSH("Clear Stencil %d", T->GetID()); diff --git a/plugins/GSdx/GSRendererDX.cpp b/plugins/GSdx/GSRendererDX.cpp index abdb5e8d8f..9c2097ec33 100644 --- a/plugins/GSdx/GSRendererDX.cpp +++ b/plugins/GSdx/GSRendererDX.cpp @@ -47,8 +47,8 @@ void GSRendererDX::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sourc GSDrawingEnvironment& env = m_env; GSDrawingContext* context = m_context; - const GSVector2i& rtsize = ds->GetSize(); - const GSVector2& rtscale = ds->GetScale(); + const GSVector2i& rtsize = ds ? ds->GetSize() : rt->GetSize(); + const GSVector2& rtscale = ds ? ds->GetScale() : rt->GetScale(); bool DATE = m_context->TEST.DATE && context->FRAME.PSM != PSM_PSMCT24; diff --git a/plugins/GSdx/GSRendererOGL.cpp b/plugins/GSdx/GSRendererOGL.cpp index 0019773597..4cd353370c 100644 --- a/plugins/GSdx/GSRendererOGL.cpp +++ b/plugins/GSdx/GSRendererOGL.cpp @@ -547,12 +547,12 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour { GL_PUSH("GL Draw from %d in %d (Depth %d)", tex && tex->m_texture ? tex->m_texture->GetID() : 0, - rt ? rt->GetID() : -1, ds->GetID()); + rt ? rt->GetID() : -1, ds ? ds->GetID() : -1); GSTexture* hdr_rt = NULL; - const GSVector2i& rtsize = ds->GetSize(); - const GSVector2& rtscale = ds->GetScale(); + const GSVector2i& rtsize = ds ? ds->GetSize() : rt->GetSize(); + const GSVector2& rtscale = ds ? ds->GetScale() : rt->GetScale(); bool DATE = m_context->TEST.DATE && m_context->FRAME.PSM != PSM_PSMCT24; bool DATE_GL42 = false; From 6cb04432271d586e9129f6ffa79699a01c50a54a Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Tue, 4 Aug 2015 19:30:12 +0200 Subject: [PATCH 2/2] gsdx: disable depth rendering if rt == depth I used to disable the RT but it doesn't work well with 50cents. It seems texture writes weren't propagated correctly to the depth buffer. Besides the game write an alpha value whereas depth is 24 bits only... --- plugins/GSdx/GSRendererHW.cpp | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/plugins/GSdx/GSRendererHW.cpp b/plugins/GSdx/GSRendererHW.cpp index 1a6fbe8fca..73322e5ddf 100644 --- a/plugins/GSdx/GSRendererHW.cpp +++ b/plugins/GSdx/GSRendererHW.cpp @@ -340,10 +340,11 @@ void GSRendererHW::Draw() // It is allowed to use the depth and rt at the same location. However at least 1 must // be disabled. // 1/ GoW uses a Cd blending on a 24 bits buffer (no alpha) - // 2/ SuperMan really draw the same value in both buffer... + // 2/ SuperMan really draws (0,0,0,0) color and a (0) 32-bits depth + // 3/ 50cents really draws (0,0,0,128) color and a (0) 24 bits depth // Note: FF DoC has both buffer at same location but disable the depth test (write?) with ZTE = 0 - const bool no_rt = (context->ALPHA.IsCd() && PRIM->ABE && (context->FRAME.PSM == 1)) || - (context->FRAME.FBP == context->ZBUF.ZBP && !PRIM->TME && !context->ZBUF.ZMSK && !context->FRAME.FBMSK && context->TEST.ZTE); + const bool no_rt = (context->ALPHA.IsCd() && PRIM->ABE && (context->FRAME.PSM == 1)); + const bool no_ds = !no_rt && (context->FRAME.FBP == context->ZBUF.ZBP && !PRIM->TME && !context->ZBUF.ZMSK && !context->FRAME.FBMSK && context->TEST.ZTE); GIFRegTEX0 TEX0; @@ -358,9 +359,10 @@ void GSRendererHW::Draw() TEX0.TBW = context->FRAME.FBW; TEX0.PSM = context->ZBUF.PSM; - GSTextureCache::Target* ds = m_tc->LookupTarget(TEX0, m_width, m_height, GSTextureCache::DepthStencil, context->DepthWrite()); + GSTextureCache::Target* ds = no_ds ? NULL : m_tc->LookupTarget(TEX0, m_width, m_height, GSTextureCache::DepthStencil, context->DepthWrite()); + GSTexture* ds_tex = ds ? ds->m_texture : NULL; - if((!rt && !no_rt) || !ds) + if(!(rt || no_rt) || !(ds || no_ds)) { GL_POP(); ASSERT(0); @@ -461,7 +463,7 @@ void GSRendererHW::Draw() { s = format("%05d_f%lld_rz0_%05x_%d.bmp", s_n, frame, context->ZBUF.Block(), context->ZBUF.PSM); - ds->m_texture->Save(root_hw+s); + ds_tex->Save(root_hw+s); } s_n++; @@ -472,7 +474,7 @@ void GSRendererHW::Draw() #endif } - if(m_hacks.m_oi && !(this->*m_hacks.m_oi)(rt_tex, ds->m_texture, tex)) + if(m_hacks.m_oi && !(this->*m_hacks.m_oi)(rt_tex, ds_tex, tex)) { s_n += 1; // keep counter sync GL_POP(); @@ -539,7 +541,7 @@ void GSRendererHW::Draw() // - DrawPrims(rt_tex, ds->m_texture, tex); + DrawPrims(rt_tex, ds_tex, tex); // @@ -560,7 +562,7 @@ void GSRendererHW::Draw() m_tc->InvalidateVideoMemType(GSTextureCache::DepthStencil, context->FRAME.Block()); } - if(zm != 0xffffffff) + if(zm != 0xffffffff && ds) { ds->m_valid = ds->m_valid.runion(r); @@ -594,7 +596,7 @@ void GSRendererHW::Draw() { s = format("%05d_f%lld_rz1_%05x_%d.bmp", s_n, frame, context->ZBUF.Block(), context->ZBUF.PSM); - ds->m_texture->Save(root_hw+s); + ds_tex->Save(root_hw+s); } s_n++; @@ -1221,7 +1223,7 @@ bool GSRendererHW::OI_SuperManReturns(GSTexture* rt, GSTexture* ds, GSTextureCac GSDrawingContext* ctx = m_context; GSVertex* v = &m_vertex.buff[0]; - if (!(ctx->FRAME.FBP == ctx->ZBUF.ZBP && !PRIM->TME && !ctx->ZBUF.ZMSK && !ctx->FRAME.FBMSK)) + if (!(ctx->FRAME.FBP == ctx->ZBUF.ZBP && !PRIM->TME && !ctx->ZBUF.ZMSK && !ctx->FRAME.FBMSK && m_vt.m_eq.rgba == 0xFFFF)) return true; // Please kill those crazy devs! @@ -1230,10 +1232,9 @@ bool GSRendererHW::OI_SuperManReturns(GSTexture* rt, GSTexture* ds, GSTextureCac ASSERT((v->RGBAQ.A << 24 | v->RGBAQ.B << 16 | v->RGBAQ.G << 8 | v->RGBAQ.R) == (int)v->XYZ.Z); // Do a direct write - double depth = (double)v->XYZ.Z * exp2(-32.0f); - m_dev->ClearDepth(ds, (float)depth); + m_dev->ClearRenderTarget(rt, GSVector4(m_vt.m_min.c)); - m_tc->InvalidateVideoMemType(GSTextureCache::RenderTarget, ctx->ZBUF.Block()); + m_tc->InvalidateVideoMemType(GSTextureCache::DepthStencil, ctx->FRAME.Block()); return false; }