From a3efc77255164b2c0e3014396d4d32a4ab5d9655 Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Sun, 12 Mar 2017 17:26:20 +0100 Subject: [PATCH] gsdx ogl: use an HLE shader to avoid upscaling line in ICO ICO uses a depth of field effect for the fog. Depth is extracted into the alpha channel of a texture. And then used as blending factor. You need a 1:1 texture/pixel mapping otherwise you will line at boundaries. In order to extract the DoF, ICO moves the depth buffer around the GS memory. Memory moves are implemented in the not-scaled world. It means that we can't have the above 1:1 ratio. And we don't know anymore that data are coming from the current depth buffer. The solution: I reused an HLE channel shader to read the depth buffer directly. This way I have the guarantee that pixel/depth are aligned. Close #1816 --- plugins/GSdx/GSRendererOGL.cpp | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/plugins/GSdx/GSRendererOGL.cpp b/plugins/GSdx/GSRendererOGL.cpp index 2553ebbc99..0c5b4ea14e 100644 --- a/plugins/GSdx/GSRendererOGL.cpp +++ b/plugins/GSdx/GSRendererOGL.cpp @@ -1494,6 +1494,40 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour // Always bind the RT. This way special effect can use it. dev->PSSetShaderResource(3, rt); + if (m_game.title == CRC::ICO) { + GSVertex* v = &m_vertex.buff[0]; + if (tex && m_vt.m_primclass == GS_SPRITE_CLASS && m_vertex.next == 2 && PRIM->ABE && // Blend texture + v[1].U == 8200 && v[1].V == 7176 && // at display resolution 512x448 + tex->m_TEX0.PSM == PSM_PSMT8H) { // i.e. read the alpha channel of a 32 bits texture + // Note potentially we can limit to TBP0:0x2800 + + // Depth buffer was moved so GSdx will invalide it which means a + // downscale. ICO uses the MSB depth bits as the texture alpha + // channel. However this depth of field effect requires + // texel:pixel mapping accuraccy. + // + // Use an HLE shader to sample depth directly as the alpha channel + GL_INS("ICO sample depth as alpha"); + m_require_full_barrier = true; + // Extract the depth as palette index + m_ps_sel.depth_fmt = 1; + m_ps_sel.channel = 3; + dev->PSSetShaderResource(4, ds); + + // We need the palette to convert the depth to the correct alpha value. + if (!tex->m_palette) { + tex->m_palette = m_dev->CreateTexture(256, 1); + + const uint32* clut = m_mem.m_clut; + int pal = GSLocalMemory::m_psm[tex->m_TEX0.PSM].pal; + tex->m_palette->Update(GSVector4i(0, 0, pal, 1), clut, pal * sizeof(clut[0])); + tex->m_initpalette = false; + + dev->PSSetShaderResource(1, tex->m_palette); + } + } + } + // rs const GSVector4& hacked_scissor = m_channel_shuffle ? GSVector4(0, 0, 1024, 1024) : m_context->scissor.in; GSVector4i scissor = GSVector4i(GSVector4(rtscale).xyxy() * hacked_scissor).rintersect(GSVector4i(rtsize).zwxy());