mirror of https://github.com/PCSX2/pcsx2.git
GS/OpenGL: Use shader+draw for CopyRectConv
This commit is contained in:
parent
f36d5fdbdf
commit
8ea24d9ff9
|
@ -1292,28 +1292,28 @@ GSTexture* GSDeviceOGL::CopyOffscreen(GSTexture* src, const GSVector4& sRect, in
|
|||
}
|
||||
|
||||
// Copy a sub part of texture (same as below but force a conversion)
|
||||
void GSDeviceOGL::CopyRectConv(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, bool at_origin)
|
||||
void GSDeviceOGL::BlitRect(GSTexture* sTex, const GSVector4i& r, const GSVector2i& dsize, bool at_origin, bool linear)
|
||||
{
|
||||
ASSERT(sTex && dTex);
|
||||
if (!(sTex && dTex))
|
||||
return;
|
||||
const GLuint sid = static_cast<GSTextureOGL*>(sTex)->GetID();
|
||||
GL_PUSH(format("CopyRectConv from %d", sid).c_str());
|
||||
|
||||
const GLuint& sid = static_cast<GSTextureOGL*>(sTex)->GetID();
|
||||
const GLuint& did = static_cast<GSTextureOGL*>(dTex)->GetID();
|
||||
// NOTE: This previously used glCopyTextureSubImage2D(), but this appears to leak memory in
|
||||
// the loading screens of Evolution Snowboarding in Intel/NVIDIA drivers.
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
GL_PUSH(format("CopyRectConv from %d to %d", sid, did).c_str());
|
||||
const GSVector4 float_r(r);
|
||||
|
||||
dTex->CommitRegion(GSVector2i(r.z, r.w));
|
||||
BeginScene();
|
||||
m_shader->BindPipeline(m_convert.ps[ShaderConvert_COPY]);
|
||||
OMSetDepthStencilState(m_convert.dss);
|
||||
OMSetBlendState();
|
||||
OMSetColorMaskState();
|
||||
PSSetShaderResource(0, sTex);
|
||||
PSSetSamplerState(linear ? m_convert.ln : m_convert.pt);
|
||||
DrawStretchRect(float_r / (GSVector4(sTex->GetSize()).xyxy()), float_r, dsize);
|
||||
EndScene();
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read);
|
||||
|
||||
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sid, 0);
|
||||
if (at_origin)
|
||||
glCopyTextureSubImage2D(did, GL_TEX_LEVEL_0, 0, 0, r.x, r.y, r.width(), r.height());
|
||||
else
|
||||
glCopyTextureSubImage2D(did, GL_TEX_LEVEL_0, r.x, r.y, r.x, r.y, r.width(), r.height());
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
// Copy a sub part of a texture into another
|
||||
|
@ -1373,7 +1373,7 @@ void GSDeviceOGL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture
|
|||
}
|
||||
|
||||
const bool draw_in_depth = (ps == m_convert.ps[ShaderConvert_RGBA8_TO_FLOAT32] || ps == m_convert.ps[ShaderConvert_RGBA8_TO_FLOAT24] ||
|
||||
ps == m_convert.ps[ShaderConvert_RGBA8_TO_FLOAT16] || ps == m_convert.ps[ShaderConvert_RGB5A1_TO_FLOAT16]);
|
||||
ps == m_convert.ps[ShaderConvert_RGBA8_TO_FLOAT16] || ps == m_convert.ps[ShaderConvert_RGB5A1_TO_FLOAT16]);
|
||||
|
||||
// Performance optimization. It might be faster to use a framebuffer blit for standard case
|
||||
// instead to emulate it with shader
|
||||
|
@ -1413,6 +1413,40 @@ void GSDeviceOGL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture
|
|||
// ************************************
|
||||
|
||||
|
||||
// Flip y axis only when we render in the backbuffer
|
||||
// By default everything is render in the wrong order (ie dx).
|
||||
// 1/ consistency between several pass rendering (interlace)
|
||||
// 2/ in case some GS code expect thing in dx order.
|
||||
// Only flipping the backbuffer is transparent (I hope)...
|
||||
GSVector4 flip_sr = sRect;
|
||||
if (static_cast<GSTextureOGL*>(dTex)->IsBackbuffer())
|
||||
{
|
||||
flip_sr.y = sRect.w;
|
||||
flip_sr.w = sRect.y;
|
||||
}
|
||||
|
||||
// ************************************
|
||||
// Texture
|
||||
// ************************************
|
||||
|
||||
PSSetShaderResource(0, sTex);
|
||||
PSSetSamplerState(linear ? m_convert.ln : m_convert.pt);
|
||||
|
||||
// ************************************
|
||||
// Draw
|
||||
// ************************************
|
||||
dTex->CommitRegion(GSVector2i((int)dRect.z + 1, (int)dRect.w + 1));
|
||||
DrawStretchRect(flip_sr, dRect, ds);
|
||||
|
||||
// ************************************
|
||||
// End
|
||||
// ************************************
|
||||
|
||||
EndScene();
|
||||
}
|
||||
|
||||
void GSDeviceOGL::DrawStretchRect(const GSVector4& sRect, const GSVector4& dRect, const GSVector2i& ds)
|
||||
{
|
||||
// Original code from DX
|
||||
const float left = dRect.x * 2 / ds.x - 1.0f;
|
||||
const float right = dRect.z * 2 / ds.x - 1.0f;
|
||||
|
@ -1426,47 +1460,17 @@ void GSDeviceOGL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture
|
|||
const float bottom = -1.0f + dRect.w * 2 / ds.y;
|
||||
#endif
|
||||
|
||||
// Flip y axis only when we render in the backbuffer
|
||||
// By default everything is render in the wrong order (ie dx).
|
||||
// 1/ consistency between several pass rendering (interlace)
|
||||
// 2/ in case some GS code expect thing in dx order.
|
||||
// Only flipping the backbuffer is transparent (I hope)...
|
||||
GSVector4 flip_sr = sRect;
|
||||
if (static_cast<GSTextureOGL*>(dTex)->IsBackbuffer())
|
||||
{
|
||||
flip_sr.y = sRect.w;
|
||||
flip_sr.w = sRect.y;
|
||||
}
|
||||
|
||||
GSVertexPT1 vertices[] =
|
||||
{
|
||||
{GSVector4(left , top , 0.0f, 0.0f) , GSVector2(flip_sr.x , flip_sr.y)} ,
|
||||
{GSVector4(right , top , 0.0f, 0.0f) , GSVector2(flip_sr.z , flip_sr.y)} ,
|
||||
{GSVector4(left , bottom, 0.0f, 0.0f) , GSVector2(flip_sr.x , flip_sr.w)} ,
|
||||
{GSVector4(right , bottom, 0.0f, 0.0f) , GSVector2(flip_sr.z , flip_sr.w)} ,
|
||||
{GSVector4(left , top , 0.0f, 0.0f) , GSVector2(sRect.x , sRect.y)} ,
|
||||
{GSVector4(right , top , 0.0f, 0.0f) , GSVector2(sRect.z , sRect.y)} ,
|
||||
{GSVector4(left , bottom, 0.0f, 0.0f) , GSVector2(sRect.x , sRect.w)} ,
|
||||
{GSVector4(right , bottom, 0.0f, 0.0f) , GSVector2(sRect.z , sRect.w)} ,
|
||||
};
|
||||
|
||||
IASetVertexBuffer(vertices, 4);
|
||||
IASetPrimitiveTopology(GL_TRIANGLE_STRIP);
|
||||
|
||||
// ************************************
|
||||
// Texture
|
||||
// ************************************
|
||||
|
||||
PSSetShaderResource(0, sTex);
|
||||
PSSetSamplerState(linear ? m_convert.ln : m_convert.pt);
|
||||
|
||||
// ************************************
|
||||
// Draw
|
||||
// ************************************
|
||||
dTex->CommitRegion(GSVector2i((int)dRect.z + 1, (int)dRect.w + 1));
|
||||
DrawPrimitive();
|
||||
|
||||
// ************************************
|
||||
// End
|
||||
// ************************************
|
||||
|
||||
EndScene();
|
||||
}
|
||||
|
||||
void GSDeviceOGL::RenderOsd(GSTexture* dt)
|
||||
|
|
|
@ -575,6 +575,8 @@ private:
|
|||
|
||||
u16 ConvertBlendEnum(u16 generic) final;
|
||||
|
||||
void DrawStretchRect(const GSVector4& sRect, const GSVector4& dRect, const GSVector2i& ds);
|
||||
|
||||
public:
|
||||
GSShaderOGL* m_shader;
|
||||
|
||||
|
@ -606,7 +608,10 @@ public:
|
|||
GSTexture* CopyOffscreen(GSTexture* src, const GSVector4& sRect, int w, int h, int format = 0, int ps_shader = 0) final;
|
||||
|
||||
void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r) final;
|
||||
void CopyRectConv(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, bool at_origin);
|
||||
|
||||
// BlitRect *does* mess with GL state, be sure to re-bind.
|
||||
void BlitRect(GSTexture* sTex, const GSVector4i& r, const GSVector2i& dsize, bool at_origin, bool linear);
|
||||
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, int shader = 0, bool linear = true) final;
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, GLuint ps, bool linear = true);
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red, bool green, bool blue, bool alpha) final;
|
||||
|
|
|
@ -1214,20 +1214,18 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
|
|||
}
|
||||
|
||||
// DATE setup, no DATE_GL45 please
|
||||
|
||||
const GSVector4i commitRect = ComputeBoundingBox(rtscale, rtsize);
|
||||
if (DATE && !DATE_GL45)
|
||||
{
|
||||
const GSVector4i dRect = ComputeBoundingBox(rtscale, rtsize);
|
||||
|
||||
// Reduce the quantity of clean function
|
||||
glScissor(dRect.x, dRect.y, dRect.width(), dRect.height());
|
||||
GLState::scissor = dRect;
|
||||
glScissor(commitRect.x, commitRect.y, commitRect.width(), commitRect.height());
|
||||
GLState::scissor = commitRect;
|
||||
|
||||
// Must be done here to avoid any GL state pertubation (clear function...)
|
||||
// Create an r32ui image that will containt primitive ID
|
||||
if (DATE_GL42)
|
||||
{
|
||||
dev->InitPrimDateTexture(rt, dRect);
|
||||
dev->InitPrimDateTexture(rt, commitRect);
|
||||
}
|
||||
else if (DATE_one)
|
||||
{
|
||||
|
@ -1235,7 +1233,7 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
|
|||
}
|
||||
else
|
||||
{
|
||||
const GSVector4 src = GSVector4(dRect) / GSVector4(rtsize.x, rtsize.y).xyxy();
|
||||
const GSVector4 src = GSVector4(commitRect) / GSVector4(rtsize.x, rtsize.y).xyxy();
|
||||
const GSVector4 dst = src * 2.0f - 1.0f;
|
||||
|
||||
GSVertexPT1 vertices[] =
|
||||
|
@ -1366,6 +1364,36 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
|
|||
m_ps_sel.atst = ps_atst;
|
||||
}
|
||||
|
||||
// rs
|
||||
const GSVector4& hacked_scissor = m_channel_shuffle ? GSVector4(0, 0, 1024, 1024) : m_context->scissor.in;
|
||||
const GSVector4i scissor = GSVector4i(GSVector4(rtscale).xyxy() * hacked_scissor).rintersect(GSVector4i(rtsize).zwxy());
|
||||
|
||||
if (rt)
|
||||
rt->CommitRegion(GSVector2i(commitRect.z, commitRect.w));
|
||||
|
||||
if (ds)
|
||||
ds->CommitRegion(GSVector2i(commitRect.z, commitRect.w));
|
||||
|
||||
if (m_ps_sel.hdr)
|
||||
{
|
||||
hdr_rt = dev->CreateTexture(rtsize.x, rtsize.y, GL_RGBA32F);
|
||||
dev->OMSetRenderTargets(hdr_rt, ds, &scissor);
|
||||
|
||||
// save blend state, since BlitRect destroys it
|
||||
const bool old_blend = GLState::blend;
|
||||
hdr_rt->CommitRegion(GSVector2i(commitRect.z, commitRect.w));
|
||||
dev->BlitRect(rt, commitRect, rt->GetSize(), false, false);
|
||||
if (old_blend)
|
||||
{
|
||||
GLState::blend = old_blend;
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dev->OMSetRenderTargets(rt, ds, &scissor);
|
||||
}
|
||||
|
||||
if (tex)
|
||||
{
|
||||
EmulateTextureSampler(tex);
|
||||
|
@ -1412,10 +1440,6 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
|
|||
}
|
||||
}
|
||||
|
||||
// rs
|
||||
const GSVector4& hacked_scissor = m_channel_shuffle ? GSVector4(0, 0, 1024, 1024) : m_context->scissor.in;
|
||||
const GSVector4i scissor = GSVector4i(GSVector4(rtscale).xyxy() * hacked_scissor).rintersect(GSVector4i(rtsize).zwxy());
|
||||
|
||||
SetupIA(sx, sy);
|
||||
|
||||
dev->OMSetColorMaskState(m_om_csel);
|
||||
|
@ -1425,14 +1449,6 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
|
|||
|
||||
dev->SetupPipeline(m_vs_sel, m_gs_sel, m_ps_sel);
|
||||
|
||||
const GSVector4i commitRect = ComputeBoundingBox(rtscale, rtsize);
|
||||
|
||||
if (rt)
|
||||
rt->CommitRegion(GSVector2i(commitRect.z, commitRect.w));
|
||||
|
||||
if (ds)
|
||||
ds->CommitRegion(GSVector2i(commitRect.z, commitRect.w));
|
||||
|
||||
if (DATE_GL42)
|
||||
{
|
||||
GL_PUSH("Date GL42");
|
||||
|
@ -1461,19 +1477,8 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
|
|||
|
||||
// Be sure that first pass is finished !
|
||||
dev->Barrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
|
||||
}
|
||||
|
||||
if (m_ps_sel.hdr)
|
||||
{
|
||||
hdr_rt = dev->CreateTexture(rtsize.x, rtsize.y, GL_RGBA32F);
|
||||
|
||||
dev->CopyRectConv(rt, hdr_rt, ComputeBoundingBox(rtscale, rtsize), false);
|
||||
|
||||
dev->OMSetRenderTargets(hdr_rt, ds, &scissor);
|
||||
}
|
||||
else
|
||||
{
|
||||
dev->OMSetRenderTargets(rt, ds, &scissor);
|
||||
dev->OMSetRenderTargets(hdr_rt ? hdr_rt : rt, ds, &scissor);
|
||||
}
|
||||
|
||||
if (ate_first_pass)
|
||||
|
@ -1560,9 +1565,8 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
|
|||
// vertices will be overwritten. Trust me you don't want to do that.
|
||||
if (hdr_rt)
|
||||
{
|
||||
const GSVector4 dRect(ComputeBoundingBox(rtscale, rtsize));
|
||||
const GSVector4 sRect = dRect / GSVector4(rtsize.x, rtsize.y).xyxy();
|
||||
dev->StretchRect(hdr_rt, sRect, rt, dRect, ShaderConvert_MOD_256, false);
|
||||
const GSVector4 sRect = GSVector4(commitRect) / GSVector4(rtsize.x, rtsize.y).xyxy();
|
||||
dev->StretchRect(hdr_rt, sRect, rt, GSVector4(commitRect), ShaderConvert_MOD_256, false);
|
||||
|
||||
dev->Recycle(hdr_rt);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue