gsdx-d3d11: SetupIA, allow sprite conversion to be done on the cpu on d3d hw renderer when applicable.

Convert sprites on the cpu instead of the gpu when applicable. Port from
Opengl.

Lines: GPU conversion.
Triangles: CPU conversion.

Disable Geometry shader when conversion is done on the cpu.
This commit is contained in:
lightningterror 2020-06-29 09:10:37 +02:00
parent 7d35892def
commit b45e524b2c
4 changed files with 29 additions and 13 deletions

View File

@ -182,8 +182,9 @@ public:
uint32 prim:2;
uint32 point:1;
uint32 line:1;
uint32 cpu_sprite:1;
uint32 _free:27;
uint32 _free:26;
};
uint32 key;

View File

@ -41,7 +41,7 @@ void GSRendererDX11::SetupIA(const float& sx, const float& sy)
D3D11_PRIMITIVE_TOPOLOGY t;
bool unscale_pt_ln = m_userHacks_enabled_unscale_ptln && (GetUpscaleMultiplier() != 1);
const bool unscale_pt_ln = m_userHacks_enabled_unscale_ptln && (GetUpscaleMultiplier() != 1);
switch (m_vt.m_primclass)
{
@ -54,6 +54,7 @@ void GSRendererDX11::SetupIA(const float& sx, const float& sy)
t = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
break;
case GS_LINE_CLASS:
if (unscale_pt_ln)
{
@ -62,16 +63,29 @@ void GSRendererDX11::SetupIA(const float& sx, const float& sy)
}
t = D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
break;
case GS_SPRITE_CLASS:
t = D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
// Lines: GPU conversion.
// Triangles: CPU conversion.
if (!m_vt.m_accurate_stq && m_vertex.next > 32) // <=> 16 sprites (based on Shadow Hearts)
{
t = D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
}
else
{
m_gs_sel.cpu_sprite = 1;
Lines2Sprites();
t = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
}
break;
case GS_TRIANGLE_CLASS:
t = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
break;
default:
__assume(0);
}

View File

@ -142,12 +142,13 @@ void GSDevice11::SetupGS(GSSelector sel, const GSConstantBuffer* cb)
{
CComPtr<ID3D11GeometryShader> gs;
bool Unscale_GSShader = (sel.point == 1 || sel.line == 1);
if((sel.prim > 0 && (sel.iip == 0 || sel.prim == 3)) || Unscale_GSShader) // geometry shader works in every case, but not needed
const bool unscale_pt_ln = (sel.point == 1 || sel.line == 1);
// Geometry shader is disabled if sprite conversion is done on the cpu (sel.cpu_sprite).
if ((sel.prim > 0 && sel.cpu_sprite == 0 && (sel.iip == 0 || sel.prim == 3)) || unscale_pt_ln)
{
auto i = std::as_const(m_gs).find(sel);
const auto i = std::as_const(m_gs).find(sel);
if(i != m_gs.end())
if (i != m_gs.end())
{
gs = i->second;
}

View File

@ -57,7 +57,7 @@ void GSRendererOGL::SetupIA(const float& sx, const float& sy)
}
GLenum t = 0;
bool unscale_pt_ln = m_userHacks_enabled_unscale_ptln && (GetUpscaleMultiplier() != 1) && GLLoader::found_geometry_shader;
const bool unscale_pt_ln = m_userHacks_enabled_unscale_ptln && (GetUpscaleMultiplier() != 1) && GLLoader::found_geometry_shader;
switch(m_vt.m_primclass)
{
@ -81,8 +81,8 @@ void GSRendererOGL::SetupIA(const float& sx, const float& sy)
case GS_SPRITE_CLASS:
// Heuristics: trade-off
// CPU conversion => ofc, more CPU ;) more bandwidth (72 bytes / sprite)
// GPU conversion => ofc, more GPU. And also more CPU due to extra shader validation stage.
// Lines: GPU conversion => ofc, more GPU. And also more CPU due to extra shader validation stage.
// Triangles: CPU conversion => ofc, more CPU ;) more bandwidth (72 bytes / sprite)
//
// Note: severals openGL operation does draw call under the wood like texture upload. So even if
// you do 10 consecutive draw with the geometry shader, you will still pay extra validation if new