diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index e2ee170f0e6c..235d31992439 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -146,6 +146,8 @@ enum BindFramebufferColorFlags { BINDFBCOLOR_MAY_COPY = 1, BINDFBCOLOR_MAY_COPY_WITH_UV = 3, BINDFBCOLOR_APPLY_TEX_OFFSET = 4, + // Used when rendering to a temporary surface (e.g. not the current render target.) + BINDFBCOLOR_FORCE_SELF = 8, }; enum DrawTextureFlags { diff --git a/GPU/D3D11/FramebufferManagerD3D11.cpp b/GPU/D3D11/FramebufferManagerD3D11.cpp index 01bfd06fb63f..69b07bb36e74 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.cpp +++ b/GPU/D3D11/FramebufferManagerD3D11.cpp @@ -553,7 +553,7 @@ void FramebufferManagerD3D11::BindFramebufferAsColorTexture(int stage, VirtualFr } else { draw_->BindFramebufferAsTexture(framebuffer->fbo, stage, Draw::FB_COLOR_BIT, 0); } - } else if (framebuffer != currentRenderVfb_) { + } else if (framebuffer != currentRenderVfb_ || (flags & BINDFBCOLOR_FORCE_SELF) != 0) { draw_->BindFramebufferAsTexture(framebuffer->fbo, stage, Draw::FB_COLOR_BIT, 0); } else { ERROR_LOG_REPORT_ONCE(d3d11SelfTexture, G3D, "Attempting to texture from target (src=%08x / target=%08x / flags=%d)", framebuffer->fb_address, currentRenderVfb_->fb_address, flags); diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index a85e5750f097..d943b91d7949 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -277,7 +277,7 @@ class TextureShaderApplierD3D11 { }; TextureShaderApplierD3D11(ID3D11DeviceContext *context, ID3D11PixelShader *pshader, ID3D11Buffer *dynamicBuffer, float bufferW, float bufferH, int renderW, int renderH, float xoff, float yoff) - : context_(context), pshader_(pshader), bufferW_(bufferW), bufferH_(bufferH), renderW_(renderW), renderH_(renderH) { + : context_(context), pshader_(pshader), vbuffer_(dynamicBuffer), bufferW_(bufferW), bufferH_(bufferH), renderW_(renderW), renderH_(renderH) { static const Pos pos[4] = { { -1, 1, 0 }, { 1, 1, 0 }, @@ -297,11 +297,6 @@ class TextureShaderApplierD3D11 { verts_[i].pos.y += yoff; verts_[i].uv = uv[i]; } - D3D11_MAPPED_SUBRESOURCE map; - context->Map(dynamicBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); - memcpy(map.pData, &verts_[0], 4 * 5 * sizeof(float)); - context->Unmap(dynamicBuffer, 0); - vbuffer_ = dynamicBuffer; } void ApplyBounds(const KnownVertexBounds &bounds, u32 uoff, u32 voff, float xoff, float yoff) { @@ -320,28 +315,34 @@ class TextureShaderApplierD3D11 { const float left = u1 * invHalfWidth - 1.0f + xoff; const float right = u2 * invHalfWidth - 1.0f + xoff; - const float top = v1 * invHalfHeight - 1.0f + yoff; - const float bottom = v2 * invHalfHeight - 1.0f + yoff; + const float top = (bufferH_ - v1) * invHalfHeight - 1.0f + yoff; + const float bottom = (bufferH_ - v2) * invHalfHeight - 1.0f + yoff; + float z = 0.0f; - // Points are: BL, BR, TL, TR. - verts_[0].pos = Pos(left, bottom, z); - verts_[1].pos = Pos(right, bottom, z); - verts_[2].pos = Pos(left, top, z); - verts_[3].pos = Pos(right, top, z); + verts_[0].pos = Pos(left, top, z); + verts_[1].pos = Pos(right, top, z); + verts_[2].pos = Pos(left, bottom, z); + verts_[3].pos = Pos(right, bottom, z); // And also the UVs, same order. const float uvleft = u1 * invWidth; const float uvright = u2 * invWidth; const float uvtop = v1 * invHeight; const float uvbottom = v2 * invHeight; - verts_[0].uv = UV(uvleft, uvbottom); - verts_[1].uv = UV(uvright, uvbottom); - verts_[2].uv = UV(uvleft, uvtop); - verts_[3].uv = UV(uvright, uvtop); + + verts_[0].uv = UV(uvleft, uvtop); + verts_[1].uv = UV(uvright, uvtop); + verts_[2].uv = UV(uvleft, uvbottom); + verts_[3].uv = UV(uvright, uvbottom); // We need to reapply the texture next time since we cropped UV. gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); } + + D3D11_MAPPED_SUBRESOURCE map; + context_->Map(vbuffer_, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); + memcpy(map.pData, &verts_[0], 4 * 5 * sizeof(float)); + context_->Unmap(vbuffer_, 0); } void Use(ID3D11VertexShader *vshader, ID3D11InputLayout *decl) { @@ -398,11 +399,11 @@ void TextureCacheD3D11::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFra shaderApply.ApplyBounds(gstate_c.vertBounds, gstate_c.curTextureXOffset, gstate_c.curTextureYOffset, xoff, yoff); shaderApply.Use(depalShaderCache_->GetDepalettizeVertexShader(), depalShaderCache_->GetInputLayout()); + draw_->BindFramebufferAsRenderTarget(depalFBO, { Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE }); context_->PSSetShaderResources(3, 1, &clutTexture); context_->PSSetSamplers(3, 1, &stockD3D11.samplerPoint2DWrap); - framebufferManagerD3D11_->BindFramebufferAsColorTexture(0, framebuffer, BINDFBCOLOR_SKIP_COPY); + framebufferManagerD3D11_->BindFramebufferAsColorTexture(0, framebuffer, BINDFBCOLOR_SKIP_COPY | BINDFBCOLOR_FORCE_SELF); context_->PSSetSamplers(0, 1, &stockD3D11.samplerPoint2DWrap); - draw_->BindFramebufferAsRenderTarget(depalFBO, { Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE }); shaderApply.Shade(); framebufferManagerD3D11_->RebindFramebuffer(); diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 6d4338117e60..321b980f4479 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -320,14 +320,14 @@ class TextureShaderApplierDX9 { static const Pos pos[4] = { {-1, 1, 0}, { 1, 1, 0}, - { 1, -1, 0}, {-1, -1, 0}, + { 1, -1, 0}, }; static const UV uv[4] = { {0, 0}, {1, 0}, - {1, 1}, {0, 1}, + {1, 1}, }; for (int i = 0; i < 4; ++i) { @@ -354,25 +354,25 @@ class TextureShaderApplierDX9 { const float left = u1 * invHalfWidth - 1.0f + xoff; const float right = u2 * invHalfWidth - 1.0f + xoff; - const float top = v1 * invHalfHeight - 1.0f + yoff; - const float bottom = v2 * invHalfHeight - 1.0f + yoff; + const float top = (bufferH_ - v1) * invHalfHeight - 1.0f + yoff; + const float bottom = (bufferH_ - v2) * invHalfHeight - 1.0f + yoff; float z = 0.0f; - // Points are: BL, BR, TR, TL. - verts_[0].pos = Pos(left, bottom, z); - verts_[1].pos = Pos(right, bottom, z); - verts_[2].pos = Pos(right, top, z); - verts_[3].pos = Pos(left, top, z); + verts_[0].pos = Pos(left, top, z); + verts_[1].pos = Pos(right, top, z); + verts_[2].pos = Pos(left, bottom, z); + verts_[3].pos = Pos(right, bottom, z); // And also the UVs, same order. const float uvleft = u1 * invWidth; const float uvright = u2 * invWidth; const float uvtop = v1 * invHeight; const float uvbottom = v2 * invHeight; - verts_[0].uv = UV(uvleft, uvbottom); - verts_[1].uv = UV(uvright, uvbottom); - verts_[2].uv = UV(uvright, uvtop); - verts_[3].uv = UV(uvleft, uvtop); + + verts_[0].uv = UV(uvleft, uvtop); + verts_[1].uv = UV(uvright, uvtop); + verts_[2].uv = UV(uvleft, uvbottom); + verts_[3].uv = UV(uvright, uvbottom); // We need to reapply the texture next time since we cropped UV. gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); @@ -396,7 +396,7 @@ class TextureShaderApplierDX9 { D3DVIEWPORT9 vp{ 0, 0, (DWORD)renderW_, (DWORD)renderH_, 0.0f, 1.0f }; device_->SetViewport(&vp); - HRESULT hr = device_->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts_, (3 + 2) * sizeof(float)); + HRESULT hr = device_->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, verts_, (3 + 2) * sizeof(float)); if (FAILED(hr)) { ERROR_LOG_REPORT(G3D, "Depal render failed: %08x", hr); } @@ -442,7 +442,7 @@ void TextureCacheDX9::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFrame device_->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_POINT); device_->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_NONE); - framebufferManagerDX9_->BindFramebufferAsColorTexture(0, framebuffer, BINDFBCOLOR_SKIP_COPY); + framebufferManagerDX9_->BindFramebufferAsColorTexture(0, framebuffer, BINDFBCOLOR_SKIP_COPY | BINDFBCOLOR_FORCE_SELF); device_->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); device_->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); device_->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE); diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 6536e8d91610..395651f24b29 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -484,7 +484,7 @@ void TextureCacheGLES::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFram shaderApply.ApplyBounds(gstate_c.vertBounds, gstate_c.curTextureXOffset, gstate_c.curTextureYOffset); shaderApply.Use(render_, drawEngine_, shadeInputLayout_); - framebufferManagerGL_->BindFramebufferAsColorTexture(0, framebuffer, BINDFBCOLOR_SKIP_COPY); + framebufferManagerGL_->BindFramebufferAsColorTexture(0, framebuffer, BINDFBCOLOR_SKIP_COPY | BINDFBCOLOR_FORCE_SELF); render_->BindTexture(TEX_SLOT_CLUT, clutTexture); render_->SetTextureSampler(TEX_SLOT_CLUT, GL_REPEAT, GL_CLAMP_TO_EDGE, GL_NEAREST, GL_NEAREST, 0.0f); diff --git a/GPU/Vulkan/FramebufferVulkan.cpp b/GPU/Vulkan/FramebufferVulkan.cpp index 91dd924a15ff..4ec89a66e1e0 100644 --- a/GPU/Vulkan/FramebufferVulkan.cpp +++ b/GPU/Vulkan/FramebufferVulkan.cpp @@ -425,7 +425,7 @@ VkImageView FramebufferManagerVulkan::BindFramebufferAsColorTexture(int stage, V draw_->BindFramebufferAsTexture(framebuffer->fbo, stage, Draw::FB_COLOR_BIT, 0); } return (VkImageView)draw_->GetNativeObject(Draw::NativeObject::BOUND_TEXTURE0_IMAGEVIEW); - } else if (framebuffer != currentRenderVfb_) { + } else if (framebuffer != currentRenderVfb_ || (flags & BINDFBCOLOR_FORCE_SELF) != 0) { draw_->BindFramebufferAsTexture(framebuffer->fbo, stage, Draw::FB_COLOR_BIT, 0); return (VkImageView)draw_->GetNativeObject(Draw::NativeObject::BOUND_TEXTURE0_IMAGEVIEW); } else {