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)
|
// 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);
|
const GLuint sid = static_cast<GSTextureOGL*>(sTex)->GetID();
|
||||||
if (!(sTex && dTex))
|
GL_PUSH(format("CopyRectConv from %d", sid).c_str());
|
||||||
return;
|
|
||||||
|
|
||||||
const GLuint& sid = static_cast<GSTextureOGL*>(sTex)->GetID();
|
// NOTE: This previously used glCopyTextureSubImage2D(), but this appears to leak memory in
|
||||||
const GLuint& did = static_cast<GSTextureOGL*>(dTex)->GetID();
|
// 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);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy a sub part of a texture into another
|
// 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] ||
|
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
|
// Performance optimization. It might be faster to use a framebuffer blit for standard case
|
||||||
// instead to emulate it with shader
|
// 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
|
// Original code from DX
|
||||||
const float left = dRect.x * 2 / ds.x - 1.0f;
|
const float left = dRect.x * 2 / ds.x - 1.0f;
|
||||||
const float right = dRect.z * 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;
|
const float bottom = -1.0f + dRect.w * 2 / ds.y;
|
||||||
#endif
|
#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[] =
|
GSVertexPT1 vertices[] =
|
||||||
{
|
{
|
||||||
{GSVector4(left , top , 0.0f, 0.0f) , GSVector2(flip_sr.x , flip_sr.y)} ,
|
{GSVector4(left , top , 0.0f, 0.0f) , GSVector2(sRect.x , sRect.y)} ,
|
||||||
{GSVector4(right , top , 0.0f, 0.0f) , GSVector2(flip_sr.z , flip_sr.y)} ,
|
{GSVector4(right , top , 0.0f, 0.0f) , GSVector2(sRect.z , sRect.y)} ,
|
||||||
{GSVector4(left , bottom, 0.0f, 0.0f) , GSVector2(flip_sr.x , flip_sr.w)} ,
|
{GSVector4(left , bottom, 0.0f, 0.0f) , GSVector2(sRect.x , sRect.w)} ,
|
||||||
{GSVector4(right , bottom, 0.0f, 0.0f) , GSVector2(flip_sr.z , flip_sr.w)} ,
|
{GSVector4(right , bottom, 0.0f, 0.0f) , GSVector2(sRect.z , sRect.w)} ,
|
||||||
};
|
};
|
||||||
|
|
||||||
IASetVertexBuffer(vertices, 4);
|
IASetVertexBuffer(vertices, 4);
|
||||||
IASetPrimitiveTopology(GL_TRIANGLE_STRIP);
|
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();
|
DrawPrimitive();
|
||||||
|
|
||||||
// ************************************
|
|
||||||
// End
|
|
||||||
// ************************************
|
|
||||||
|
|
||||||
EndScene();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GSDeviceOGL::RenderOsd(GSTexture* dt)
|
void GSDeviceOGL::RenderOsd(GSTexture* dt)
|
||||||
|
|
|
@ -575,6 +575,8 @@ private:
|
||||||
|
|
||||||
u16 ConvertBlendEnum(u16 generic) final;
|
u16 ConvertBlendEnum(u16 generic) final;
|
||||||
|
|
||||||
|
void DrawStretchRect(const GSVector4& sRect, const GSVector4& dRect, const GSVector2i& ds);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GSShaderOGL* m_shader;
|
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;
|
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 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, 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, 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;
|
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
|
// DATE setup, no DATE_GL45 please
|
||||||
|
const GSVector4i commitRect = ComputeBoundingBox(rtscale, rtsize);
|
||||||
if (DATE && !DATE_GL45)
|
if (DATE && !DATE_GL45)
|
||||||
{
|
{
|
||||||
const GSVector4i dRect = ComputeBoundingBox(rtscale, rtsize);
|
|
||||||
|
|
||||||
// Reduce the quantity of clean function
|
// Reduce the quantity of clean function
|
||||||
glScissor(dRect.x, dRect.y, dRect.width(), dRect.height());
|
glScissor(commitRect.x, commitRect.y, commitRect.width(), commitRect.height());
|
||||||
GLState::scissor = dRect;
|
GLState::scissor = commitRect;
|
||||||
|
|
||||||
// Must be done here to avoid any GL state pertubation (clear function...)
|
// Must be done here to avoid any GL state pertubation (clear function...)
|
||||||
// Create an r32ui image that will containt primitive ID
|
// Create an r32ui image that will containt primitive ID
|
||||||
if (DATE_GL42)
|
if (DATE_GL42)
|
||||||
{
|
{
|
||||||
dev->InitPrimDateTexture(rt, dRect);
|
dev->InitPrimDateTexture(rt, commitRect);
|
||||||
}
|
}
|
||||||
else if (DATE_one)
|
else if (DATE_one)
|
||||||
{
|
{
|
||||||
|
@ -1235,7 +1233,7 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
|
||||||
}
|
}
|
||||||
else
|
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;
|
const GSVector4 dst = src * 2.0f - 1.0f;
|
||||||
|
|
||||||
GSVertexPT1 vertices[] =
|
GSVertexPT1 vertices[] =
|
||||||
|
@ -1366,6 +1364,36 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
|
||||||
m_ps_sel.atst = ps_atst;
|
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)
|
if (tex)
|
||||||
{
|
{
|
||||||
EmulateTextureSampler(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);
|
SetupIA(sx, sy);
|
||||||
|
|
||||||
dev->OMSetColorMaskState(m_om_csel);
|
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);
|
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)
|
if (DATE_GL42)
|
||||||
{
|
{
|
||||||
GL_PUSH("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 !
|
// Be sure that first pass is finished !
|
||||||
dev->Barrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
|
dev->Barrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
|
||||||
}
|
|
||||||
|
|
||||||
if (m_ps_sel.hdr)
|
dev->OMSetRenderTargets(hdr_rt ? hdr_rt : rt, ds, &scissor);
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ate_first_pass)
|
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.
|
// vertices will be overwritten. Trust me you don't want to do that.
|
||||||
if (hdr_rt)
|
if (hdr_rt)
|
||||||
{
|
{
|
||||||
const GSVector4 dRect(ComputeBoundingBox(rtscale, rtsize));
|
const GSVector4 sRect = GSVector4(commitRect) / GSVector4(rtsize.x, rtsize.y).xyxy();
|
||||||
const GSVector4 sRect = dRect / GSVector4(rtsize.x, rtsize.y).xyxy();
|
dev->StretchRect(hdr_rt, sRect, rt, GSVector4(commitRect), ShaderConvert_MOD_256, false);
|
||||||
dev->StretchRect(hdr_rt, sRect, rt, dRect, ShaderConvert_MOD_256, false);
|
|
||||||
|
|
||||||
dev->Recycle(hdr_rt);
|
dev->Recycle(hdr_rt);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue