GSdx: Unscale Point and Line Direct3D11 port

Ports the "Unscale Point and Line" hack to the Direct3D11 Hardware renderer.

And enables the "Unscale Point and Line" hack for Custom Resolutions with Direct3D11 and OpenGL.
This commit is contained in:
FlatOutPS2 2017-03-03 22:18:49 +01:00 committed by Gregory Hainaut
parent 117c249595
commit 557b672232
18 changed files with 371 additions and 232 deletions

View File

@ -30,6 +30,7 @@ GSDevice11::GSDevice11()
{
memset(&m_state, 0, sizeof(m_state));
memset(&m_vs_cb_cache, 0, sizeof(m_vs_cb_cache));
memset(&m_gs_cb_cache, 0, sizeof(m_gs_cb_cache));
memset(&m_ps_cb_cache, 0, sizeof(m_ps_cb_cache));
FXAA_Compiled = false;
@ -37,6 +38,12 @@ GSDevice11::GSDevice11()
m_state.topology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
m_state.bf = -1;
if (theApp.GetConfigB("UserHacks")) {
UserHacks_unscale_pt_ln = theApp.GetConfigB("UserHacks_unscale_point_line");
} else {
UserHacks_unscale_pt_ln = false;
}
}
GSDevice11::~GSDevice11()
@ -699,7 +706,7 @@ void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
//sel.prim = 2; //Triangle Strip
//SetupGS(sel);
GSSetShader(NULL);
GSSetShader(NULL, NULL);
/*END OF HACK*/
@ -895,7 +902,7 @@ void GSDevice11::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vert
// gs
GSSetShader(NULL);
GSSetShader(NULL, NULL);
// ps
@ -1105,7 +1112,7 @@ void GSDevice11::VSSetShader(ID3D11VertexShader* vs, ID3D11Buffer* vs_cb)
}
}
void GSDevice11::GSSetShader(ID3D11GeometryShader* gs)
void GSDevice11::GSSetShader(ID3D11GeometryShader* gs, ID3D11Buffer* gs_cb)
{
if(m_state.gs != gs)
{
@ -1113,6 +1120,13 @@ void GSDevice11::GSSetShader(ID3D11GeometryShader* gs)
m_ctx->GSSetShader(gs, NULL, 0);
}
if (m_state.gs_cb != gs_cb)
{
m_state.gs_cb = gs_cb;
m_ctx->GSSetConstantBuffers(0, 1, &gs_cb);
}
}
void GSDevice11::PSSetShaderResources(GSTexture* sr0, GSTexture* sr1)

View File

@ -57,6 +57,8 @@ class GSDevice11 : public GSDeviceDX
int spritehack;
bool isNative;
bool UserHacks_unscale_pt_ln;
struct
{
ID3D11Buffer* vb;
@ -67,6 +69,7 @@ class GSDevice11 : public GSDeviceDX
ID3D11VertexShader* vs;
ID3D11Buffer* vs_cb;
ID3D11GeometryShader* gs;
ID3D11Buffer* gs_cb;
ID3D11ShaderResourceView* ps_srv[16];
ID3D11PixelShader* ps;
ID3D11Buffer* ps_cb;
@ -145,6 +148,7 @@ public: // TODO
hash_map<uint32, GSVertexShader11 > m_vs;
CComPtr<ID3D11Buffer> m_vs_cb;
hash_map<uint32, CComPtr<ID3D11GeometryShader> > m_gs;
CComPtr<ID3D11Buffer> m_gs_cb;
hash_map<uint64, CComPtr<ID3D11PixelShader> > m_ps;
CComPtr<ID3D11Buffer> m_ps_cb;
hash_map<uint32, CComPtr<ID3D11SamplerState> > m_ps_ss;
@ -154,6 +158,7 @@ public: // TODO
hash_map<uint32, CComPtr<ID3D11BlendState> > m_om_bs;
VSConstantBuffer m_vs_cb_cache;
GSConstantBuffer m_gs_cb_cache;
PSConstantBuffer m_ps_cb_cache;
bool CreateTextureFX();
@ -202,7 +207,7 @@ public:
void IASetInputLayout(ID3D11InputLayout* layout);
void IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY topology);
void VSSetShader(ID3D11VertexShader* vs, ID3D11Buffer* vs_cb);
void GSSetShader(ID3D11GeometryShader* gs);
void GSSetShader(ID3D11GeometryShader* gs, ID3D11Buffer* gs_cb = NULL);
void PSSetShaderResources(GSTexture* sr0, GSTexture* sr1);
void PSSetShaderResource(int i, GSTexture* sr);
void PSSetShaderResourceView(int i, ID3D11ShaderResourceView* srv);
@ -217,7 +222,7 @@ public:
void OMSetRenderTargets(const GSVector2i& rtsize, int count, ID3D11UnorderedAccessView** uav, uint32* counters, const GSVector4i* scissor = NULL);
void SetupVS(VSSelector sel, const VSConstantBuffer* cb);
void SetupGS(GSSelector sel);
void SetupGS(GSSelector sel, const GSConstantBuffer* cb);
void SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel);
void SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix);

View File

@ -241,7 +241,7 @@ public:
void CompileShader(const char *source, size_t size, const char *filename, const string& entry, const D3D_SHADER_MACRO* macro, IDirect3DPixelShader9** ps);
void SetupVS(VSSelector sel, const VSConstantBuffer* cb);
void SetupGS(GSSelector sel) {}
void SetupGS(GSSelector sel, const GSConstantBuffer* cb) {}
void SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel);
void SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix);

View File

@ -125,6 +125,21 @@ public:
}
};
struct alignas(32) GSConstantBuffer
{
GSVector2 PointSize;
struct GSConstantBuffer()
{
PointSize = GSVector2(0);
}
__forceinline bool Update(const GSConstantBuffer* cb)
{
return true;
}
};
struct GSSelector
{
union
@ -133,14 +148,19 @@ public:
{
uint32 iip:1;
uint32 prim:2;
uint32 point:1;
uint32 line:1;
uint32 _free:27;
};
uint32 key;
};
operator uint32() {return key & 0x7;}
operator uint32() {return key;}
GSSelector() : key(0) {}
GSSelector(uint32 k) : key(k) {}
};
struct PSSelector
@ -286,7 +306,7 @@ public:
void GetFeatureLevel(D3D_FEATURE_LEVEL& level) const {level = m_shader.level;}
virtual void SetupVS(VSSelector sel, const VSConstantBuffer* cb) = 0;
virtual void SetupGS(GSSelector sel) = 0;
virtual void SetupGS(GSSelector sel, const GSConstantBuffer* cb) = 0;
virtual void SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel) = 0;
virtual void SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix) = 0;

View File

@ -61,8 +61,7 @@ void GSRendererDX::EmulateAtst(const int pass, const GSTextureCache::Source* tex
case ATST_LESS:
if (tex && tex->m_spritehack_t) {
m_ps_sel.atst = 0;
}
else {
} else {
ps_cb.FogColor_AREF.a = (float)m_context->TEST.AREF - 0.1f;
m_ps_sel.atst = 1;
}
@ -89,7 +88,8 @@ void GSRendererDX::EmulateAtst(const int pass, const GSTextureCache::Source* tex
ps_cb.FogColor_AREF.a = (float)m_context->TEST.AREF;
m_ps_sel.atst = 4;
break;
case ATST_NEVER:
case ATST_NEVER: // Draw won't be done so no need to implement it in shader
case ATST_ALWAYS:
default:
m_ps_sel.atst = 0;
@ -426,10 +426,8 @@ void GSRendererDX::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sourc
// gs
GSDeviceDX::GSSelector gs_sel;
gs_sel.iip = PRIM->IIP;
gs_sel.prim = m_vt.m_primclass;
m_gs_sel.iip = PRIM->IIP;
m_gs_sel.prim = m_vt.m_primclass;
// ps
@ -629,11 +627,11 @@ void GSRendererDX::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sourc
uint8 afix = m_context->ALPHA.FIX;
SetupIA();
SetupIA(sx, sy);
dev->SetupOM(om_dssel, om_bsel, afix);
dev->SetupVS(vs_sel, &vs_cb);
dev->SetupGS(gs_sel);
dev->SetupGS(m_gs_sel, &gs_cb);
dev->SetupPS(m_ps_sel, &ps_cb, m_ps_ssel);
// draw

View File

@ -38,7 +38,7 @@ protected:
void EmulateZbuffer();
void EmulateTextureSampler(const GSTextureCache::Source* tex);
virtual void DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex);
virtual void SetupIA() = 0;
virtual void SetupIA(const float& sx, const float& sy) = 0;
virtual void UpdateFBA(GSTexture* rt) {}
unsigned int UserHacks_TCOffset;
@ -57,9 +57,11 @@ protected:
GSDeviceDX::PSSelector m_ps_sel;
GSDeviceDX::PSSamplerSelector m_ps_ssel;
GSDeviceDX::GSSelector m_gs_sel;
GSDeviceDX::PSConstantBuffer ps_cb;
GSDeviceDX::VSConstantBuffer vs_cb;
GSDeviceDX::GSConstantBuffer gs_cb;
public:
GSRendererDX(GSTextureCache* tc, const GSVector2& pixelcenter = GSVector2(0));

View File

@ -27,6 +27,11 @@
GSRendererDX11::GSRendererDX11()
: GSRendererDX(new GSTextureCache11(this), GSVector2(-0.5f))
{
if (theApp.GetConfigB("UserHacks")) {
UserHacks_unscale_pt_ln = theApp.GetConfigB("UserHacks_unscale_point_line");
} else {
UserHacks_unscale_pt_ln = false;
}
}
bool GSRendererDX11::CreateDevice(GSDevice* dev)
@ -37,10 +42,52 @@ bool GSRendererDX11::CreateDevice(GSDevice* dev)
return true;
}
void GSRendererDX11::SetupIA()
void GSRendererDX11::SetupIA(const float& sx, const float& sy)
{
GSDevice11* dev = (GSDevice11*)m_dev;
D3D11_PRIMITIVE_TOPOLOGY t;
bool unscale_hack = UserHacks_unscale_pt_ln && (GetUpscaleMultiplier() != 1);
switch (m_vt.m_primclass)
{
case GS_POINT_CLASS:
if (unscale_hack) {
m_gs_sel.point = 1;
gs_cb.PointSize = GSVector2(16.0f * sx, 16.0f * sy);
}
t = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
break;
case GS_LINE_CLASS:
if (unscale_hack) {
m_gs_sel.line = 1;
gs_cb.PointSize = GSVector2(16.0f * sx, 16.0f * sy);
}
t = D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
break;
case GS_SPRITE_CLASS:
if (!m_vt.m_accurate_stq && m_vertex.next > 32) { // <=> 16 sprites (based on Shadow Hearts)
t = D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
} else {
Lines2Sprites();
t = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
}
break;
case GS_TRIANGLE_CLASS:
t = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
break;
default:
__assume(0);
}
void* ptr = NULL;
if(dev->IAMapVertexBuffer(&ptr, sizeof(GSVertex), m_vertex.next))
@ -61,24 +108,5 @@ void GSRendererDX11::SetupIA()
}
dev->IASetIndexBuffer(m_index.buff, m_index.tail);
D3D11_PRIMITIVE_TOPOLOGY t;
switch(m_vt.m_primclass)
{
case GS_POINT_CLASS:
t = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
break;
case GS_LINE_CLASS:
case GS_SPRITE_CLASS:
t = D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
break;
case GS_TRIANGLE_CLASS:
t = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
break;
default:
__assume(0);
}
dev->IASetPrimitiveTopology(t);
}

View File

@ -27,8 +27,10 @@
class GSRendererDX11 : public GSRendererDX
{
bool UserHacks_unscale_pt_ln;
protected:
void SetupIA();
void SetupIA(const float& sx, const float& sy);
public:
GSRendererDX11();

View File

@ -56,7 +56,7 @@ bool GSRendererDX9::CreateDevice(GSDevice* dev)
return true;
}
void GSRendererDX9::SetupIA()
void GSRendererDX9::SetupIA(const float& sx, const float& sy)
{
D3DPRIMITIVETYPE topology;
@ -106,62 +106,7 @@ void GSRendererDX9::SetupIA()
// each sprite converted to quad needs twice the space
while(m_vertex.tail * 2 > m_vertex.maxcount)
{
GrowVertexBuffer();
}
// assume vertices are tightly packed and sequentially indexed (it should be the case)
if(m_vertex.next >= 2)
{
size_t count = m_vertex.next;
int i = (int)count * 2 - 4;
GSVertex* s = &m_vertex.buff[count - 2];
GSVertex* q = &m_vertex.buff[count * 2 - 4];
uint32* RESTRICT index = &m_index.buff[count * 3 - 6];
for(; i >= 0; i -= 4, s -= 2, q -= 4, index -= 6)
{
GSVertex v0 = s[0];
GSVertex v1 = s[1];
v0.RGBAQ = v1.RGBAQ;
v0.XYZ.Z = v1.XYZ.Z;
v0.FOG = v1.FOG;
q[0] = v0;
q[3] = v1;
// swap x, s, u
uint16 x = v0.XYZ.X;
v0.XYZ.X = v1.XYZ.X;
v1.XYZ.X = x;
float s = v0.ST.S;
v0.ST.S = v1.ST.S;
v1.ST.S = s;
uint16 u = v0.U;
v0.U = v1.U;
v1.U = u;
q[1] = v0;
q[2] = v1;
index[0] = i + 0;
index[1] = i + 1;
index[2] = i + 2;
index[3] = i + 1;
index[4] = i + 2;
index[5] = i + 3;
}
m_vertex.head = m_vertex.tail = m_vertex.next = count * 2;
m_index.tail = count * 3;
}
Lines2Sprites();
break;

View File

@ -34,7 +34,7 @@ protected:
Direct3DBlendState9 bs;
} m_fba;
void SetupIA();
void SetupIA(const float& sx, const float& sy);
void UpdateFBA(GSTexture* rt);
public:

View File

@ -267,6 +267,83 @@ GSTexture* GSRendererHW::GetFeedbackOutput()
return t;
}
void GSRendererHW::Lines2Sprites()
{
ASSERT(m_vt.m_primclass == GS_SPRITE_CLASS);
// each sprite converted to quad needs twice the space
while (m_vertex.tail * 2 > m_vertex.maxcount)
{
GrowVertexBuffer();
}
// assume vertices are tightly packed and sequentially indexed (it should be the case)
if (m_vertex.next >= 2)
{
size_t count = m_vertex.next;
int i = (int)count * 2 - 4;
GSVertex* s = &m_vertex.buff[count - 2];
GSVertex* q = &m_vertex.buff[count * 2 - 4];
uint32* RESTRICT index = &m_index.buff[count * 3 - 6];
for (; i >= 0; i -= 4, s -= 2, q -= 4, index -= 6)
{
GSVertex v0 = s[0];
GSVertex v1 = s[1];
v0.RGBAQ = v1.RGBAQ;
v0.XYZ.Z = v1.XYZ.Z;
v0.FOG = v1.FOG;
if (PRIM->TME && !PRIM->FST) {
GSVector4 st0 = GSVector4::loadl(&v0.ST.u64);
GSVector4 st1 = GSVector4::loadl(&v1.ST.u64);
GSVector4 Q = GSVector4(v1.RGBAQ.Q, v1.RGBAQ.Q, v1.RGBAQ.Q, v1.RGBAQ.Q);
GSVector4 st = st0.upld(st1) / Q;
GSVector4::storel(&v0.ST.u64, st);
GSVector4::storeh(&v1.ST.u64, st);
v0.RGBAQ.Q = 1.0f;
v1.RGBAQ.Q = 1.0f;
}
q[0] = v0;
q[3] = v1;
// swap x, s, u
uint16 x = v0.XYZ.X;
v0.XYZ.X = v1.XYZ.X;
v1.XYZ.X = x;
float s = v0.ST.S;
v0.ST.S = v1.ST.S;
v1.ST.S = s;
uint16 u = v0.U;
v0.U = v1.U;
v1.U = u;
q[1] = v0;
q[2] = v1;
index[0] = i + 0;
index[1] = i + 1;
index[2] = i + 2;
index[3] = i + 1;
index[4] = i + 2;
index[5] = i + 3;
}
m_vertex.head = m_vertex.tail = m_vertex.next = count * 2;
m_index.tail = count * 3;
}
}
GSVector4 GSRendererHW::RealignTargetTextureCoordinate(const GSTextureCache::Source* tex)
{
if (m_userHacks_HPO <= 1 || GetUpscaleMultiplier() == 1) return GSVector4(0.0f);

View File

@ -167,6 +167,7 @@ public:
GSVector2i GetCustomResolution();
void SetScaling();
GSVector4 RealignTargetTextureCoordinate(const GSTextureCache::Source* tex);
void Lines2Sprites();
void Reset();
void VSync(int field);

View File

@ -61,83 +61,6 @@ bool GSRendererOGL::CreateDevice(GSDevice* dev)
return GSRenderer::CreateDevice(dev);
}
void GSRendererOGL::Lines2Sprites()
{
ASSERT(m_vt.m_primclass == GS_SPRITE_CLASS);
// each sprite converted to quad needs twice the space
while(m_vertex.tail * 2 > m_vertex.maxcount)
{
GrowVertexBuffer();
}
// assume vertices are tightly packed and sequentially indexed (it should be the case)
if (m_vertex.next >= 2)
{
size_t count = m_vertex.next;
int i = (int)count * 2 - 4;
GSVertex* s = &m_vertex.buff[count - 2];
GSVertex* q = &m_vertex.buff[count * 2 - 4];
uint32* RESTRICT index = &m_index.buff[count * 3 - 6];
for(; i >= 0; i -= 4, s -= 2, q -= 4, index -= 6)
{
GSVertex v0 = s[0];
GSVertex v1 = s[1];
v0.RGBAQ = v1.RGBAQ;
v0.XYZ.Z = v1.XYZ.Z;
v0.FOG = v1.FOG;
if (PRIM->TME && !PRIM->FST) {
GSVector4 st0 = GSVector4::loadl(&v0.ST.u64);
GSVector4 st1 = GSVector4::loadl(&v1.ST.u64);
GSVector4 Q = GSVector4(v1.RGBAQ.Q, v1.RGBAQ.Q, v1.RGBAQ.Q, v1.RGBAQ.Q);
GSVector4 st = st0.upld(st1) / Q;
GSVector4::storel(&v0.ST.u64, st);
GSVector4::storeh(&v1.ST.u64, st);
v0.RGBAQ.Q = 1.0f;
v1.RGBAQ.Q = 1.0f;
}
q[0] = v0;
q[3] = v1;
// swap x, s, u
uint16 x = v0.XYZ.X;
v0.XYZ.X = v1.XYZ.X;
v1.XYZ.X = x;
float s = v0.ST.S;
v0.ST.S = v1.ST.S;
v1.ST.S = s;
uint16 u = v0.U;
v0.U = v1.U;
v1.U = u;
q[1] = v0;
q[2] = v1;
index[0] = i + 0;
index[1] = i + 1;
index[2] = i + 2;
index[3] = i + 1;
index[4] = i + 2;
index[5] = i + 3;
}
m_vertex.head = m_vertex.tail = m_vertex.next = count * 2;
m_index.tail = count * 3;
}
}
void GSRendererOGL::SetupIA(const float& sx, const float& sy)
{
GL_PUSH("IA");
@ -151,7 +74,7 @@ void GSRendererOGL::SetupIA(const float& sx, const float& sy)
}
GLenum t = 0;
bool unscale_hack = UserHacks_unscale_pt_ln & (GetUpscaleMultiplier() > 1) & GLLoader::found_geometry_shader;
bool unscale_hack = UserHacks_unscale_pt_ln && (GetUpscaleMultiplier() != 1) && GLLoader::found_geometry_shader;
switch(m_vt.m_primclass)
{

View File

@ -75,7 +75,6 @@ class GSRendererOGL final : public GSRendererHW
private:
inline void ResetStates();
inline void Lines2Sprites();
inline void SetupIA(const float& sx, const float& sy);
inline void EmulateTextureShuffleAndFbmask();
inline void EmulateChannelShuffle(GSTexture** rt, const GSTextureCache::Source* tex);

View File

@ -720,9 +720,9 @@ void GSHacksDlg::OnInit()
EnableWindow(GetDlgItem(m_hWnd, IDC_TC_DEPTH), ogl);
EnableWindow(GetDlgItem(m_hWnd, IDC_TRI_FILTER), ogl);
EnableWindow(GetDlgItem(m_hWnd, IDC_TRI_FILTER_TEXT), ogl);
EnableWindow(GetDlgItem(m_hWnd, IDC_UNSCALE_POINT_LINE), ogl && !native);
// Upscaling hacks:
EnableWindow(GetDlgItem(m_hWnd, IDC_UNSCALE_POINT_LINE), !dx9 && !native);
EnableWindow(GetDlgItem(m_hWnd, IDC_SPRITEHACK), !native);
EnableWindow(GetDlgItem(m_hWnd, IDC_WILDHACK), !native);
EnableWindow(GetDlgItem(m_hWnd, IDC_ALIGN_SPRITE), !native);

View File

@ -42,6 +42,16 @@ bool GSDevice11::CreateTextureFX()
memset(&bd, 0, sizeof(bd));
bd.ByteWidth = sizeof(GSConstantBuffer);
bd.Usage = D3D11_USAGE_DEFAULT;
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
hr = m_dev->CreateBuffer(&bd, NULL, &m_gs_cb);
if (FAILED(hr)) return false;
memset(&bd, 0, sizeof(bd));
bd.ByteWidth = sizeof(PSConstantBuffer);
bd.Usage = D3D11_USAGE_DEFAULT;
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
@ -78,6 +88,10 @@ bool GSDevice11::CreateTextureFX()
SetupVS(sel, &cb);
GSConstantBuffer gcb;
SetupGS(GSSelector(1), &gcb);
//
return true;
@ -139,11 +153,12 @@ void GSDevice11::SetupVS(VSSelector sel, const VSConstantBuffer* cb)
IASetInputLayout(i->second.il);
}
void GSDevice11::SetupGS(GSSelector sel)
void GSDevice11::SetupGS(GSSelector sel, const GSConstantBuffer* cb)
{
CComPtr<ID3D11GeometryShader> gs;
if(sel.prim > 0 && (sel.iip == 0 || sel.prim == 3)) // geometry shader works in every case, but not needed
bool Unscale_GSShader = (sel.point == 1 || sel.line == 1) && UserHacks_unscale_pt_ln;
if((sel.prim > 0 && (sel.iip == 0 || sel.prim == 3)) || Unscale_GSShader) // geometry shader works in every case, but not needed
{
hash_map<uint32, CComPtr<ID3D11GeometryShader> >::const_iterator i = m_gs.find(sel);
@ -153,15 +168,19 @@ void GSDevice11::SetupGS(GSSelector sel)
}
else
{
string str[2];
string str[4];
str[0] = format("%d", sel.iip);
str[1] = format("%d", sel.prim);
str[2] = format("%d", sel.point);
str[3] = format("%d", sel.line);
D3D_SHADER_MACRO macro[] =
{
{"GS_IIP", str[0].c_str()},
{"GS_PRIM", str[1].c_str()},
{"GS_POINT", str[2].c_str()},
{"GS_LINE", str[3].c_str()},
{NULL, NULL},
};
@ -173,7 +192,15 @@ void GSDevice11::SetupGS(GSSelector sel)
}
}
GSSetShader(gs);
if (m_gs_cb_cache.Update(cb))
{
ID3D11DeviceContext* ctx = m_ctx;
ctx->UpdateSubresource(m_gs_cb, 0, NULL, cb, 0, 0);
}
GSSetShader(gs, m_gs_cb);
}
void GSDevice11::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel)

View File

@ -17,6 +17,8 @@
#ifndef GS_IIP
#define GS_IIP 0
#define GS_PRIM 3
#define GS_POINT 0
#define GS_LINE 0
#endif
#ifndef PS_FST
@ -107,6 +109,11 @@ cbuffer cb1
float4 TC_OffsetHack;
};
cbuffer cb2
{
float2 PointSize;
};
float4 sample_c(float2 uv)
{
if (ATI_SUCKS && PS_POINT_SAMPLER)
@ -630,7 +637,7 @@ VS_OUTPUT vs_main(VS_INPUT input)
return output;
}
#if GS_PRIM == 0
#if GS_PRIM == 0 && GS_POINT == 0
[maxvertexcount(1)]
void gs_main(point VS_OUTPUT input[1], inout PointStream<VS_OUTPUT> stream)
@ -638,7 +645,44 @@ void gs_main(point VS_OUTPUT input[1], inout PointStream<VS_OUTPUT> stream)
stream.Append(input[0]);
}
#elif GS_PRIM == 1
#elif GS_PRIM == 0 && GS_POINT == 1
[maxvertexcount(6)]
void gs_main(point VS_OUTPUT input[1], inout TriangleStream<VS_OUTPUT> stream)
{
// Transform a point to a NxN sprite
VS_OUTPUT Point = input[0];
// Get new position
float4 lt_p = input[0].p;
float4 rb_p = input[0].p + float4(PointSize.x, PointSize.y, 0.0f, 0.0f);
float4 lb_p = rb_p;
float4 rt_p = rb_p;
lb_p.x = lt_p.x;
rt_p.y = lt_p.y;
// Triangle 1
Point.p = lt_p;
stream.Append(Point);
Point.p = lb_p;
stream.Append(Point);
Point.p = rt_p;
stream.Append(Point);
// Triangle 2
Point.p = lb_p;
stream.Append(Point);
Point.p = rt_p;
stream.Append(Point);
Point.p = rb_p;
stream.Append(Point);
}
#elif GS_PRIM == 1 && GS_LINE == 0
[maxvertexcount(2)]
void gs_main(line VS_OUTPUT input[2], inout LineStream<VS_OUTPUT> stream)
@ -651,6 +695,54 @@ void gs_main(line VS_OUTPUT input[2], inout LineStream<VS_OUTPUT> stream)
stream.Append(input[1]);
}
#elif GS_PRIM == 1 && GS_LINE == 1
[maxvertexcount(6)]
void gs_main(line VS_OUTPUT input[2], inout TriangleStream<VS_OUTPUT> stream)
{
// Transform a line to a thick line-sprite
VS_OUTPUT left = input[0];
VS_OUTPUT right = input[1];
float2 lt_p = input[0].p.xy;
float2 rt_p = input[1].p.xy;
// Potentially there is faster math
float2 line_vector = normalize(rt_p.xy - lt_p.xy);
float2 line_normal = float2(line_vector.y, -line_vector.x);
float2 line_width = (line_normal * PointSize) / 2;
lt_p -= line_width;
rt_p -= line_width;
float2 lb_p = input[0].p.xy + line_width;
float2 rb_p = input[1].p.xy + line_width;
#if GS_IIP == 0
left.c = right.c;
#endif
// Triangle 1
left.p.xy = lt_p;
stream.Append(left);
left.p.xy = lb_p;
stream.Append(left);
right.p.xy = rt_p;
stream.Append(right);
stream.RestartStrip();
// Triangle 2
left.p.xy = lb_p;
stream.Append(left);
right.p.xy = rt_p;
stream.Append(right);
right.p.xy = rb_p;
stream.Append(right);
stream.RestartStrip();
}
#elif GS_PRIM == 2
[maxvertexcount(3)]
@ -671,27 +763,32 @@ void gs_main(triangle VS_OUTPUT input[3], inout TriangleStream<VS_OUTPUT> stream
[maxvertexcount(4)]
void gs_main(line VS_OUTPUT input[2], inout TriangleStream<VS_OUTPUT> stream)
{
input[0].p.z = input[1].p.z;
input[0].t.zw = input[1].t.zw;
VS_OUTPUT lt = input[0];
VS_OUTPUT rb = input[1];
// flat depth
lt.p.z = rb.p.z;
// flat fog and texture perspective
lt.t.zw = rb.t.zw;
// flat color
#if GS_IIP == 0
input[0].c = input[1].c;
lt.c = rb.c;
#endif
VS_OUTPUT lb = input[1];
// Swap texture and position coordinate
VS_OUTPUT lb = rb;
lb.p.x = lt.p.x;
lb.t.x = lt.t.x;
lb.p.x = input[0].p.x;
lb.t.x = input[0].t.x;
VS_OUTPUT rt = rb;
rt.p.y = lt.p.y;
rt.t.y = lt.t.y;
VS_OUTPUT rt = input[1];
rt.p.y = input[0].p.y;
rt.t.y = input[0].t.y;
stream.Append(input[0]);
stream.Append(lt);
stream.Append(lb);
stream.Append(rt);
stream.Append(input[1]);
stream.Append(rb);
}
#endif

View File

@ -101,6 +101,7 @@
#define IDC_MEMORY_WRAPPING 2122
#define IDC_TRI_FILTER 2123
#define IDC_TRI_FILTER_TEXT 2124
#define IDC_UNSCALE_POINT_LINE 2125
// Shader:
#define IDC_SHADEBOOST 2140
#define IDC_FXAA 2141