From 557b672232c7cc6b10e8811d956decfee091c459 Mon Sep 17 00:00:00 2001 From: FlatOutPS2 Date: Fri, 3 Mar 2017 22:18:49 +0100 Subject: [PATCH] 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. --- plugins/GSdx/GSDevice11.cpp | 22 +++++- plugins/GSdx/GSDevice11.h | 9 ++- plugins/GSdx/GSDevice9.h | 2 +- plugins/GSdx/GSDeviceDX.h | 24 +++++- plugins/GSdx/GSRendererDX.cpp | 82 ++++++++++---------- plugins/GSdx/GSRendererDX.h | 4 +- plugins/GSdx/GSRendererDX11.cpp | 68 ++++++++++++----- plugins/GSdx/GSRendererDX11.h | 4 +- plugins/GSdx/GSRendererDX9.cpp | 59 +------------- plugins/GSdx/GSRendererDX9.h | 2 +- plugins/GSdx/GSRendererHW.cpp | 77 +++++++++++++++++++ plugins/GSdx/GSRendererHW.h | 1 + plugins/GSdx/GSRendererOGL.cpp | 79 +------------------ plugins/GSdx/GSRendererOGL.h | 1 - plugins/GSdx/GSSettingsDlg.cpp | 2 +- plugins/GSdx/GSTextureFX11.cpp | 35 ++++++++- plugins/GSdx/res/tfx.fx | 131 +++++++++++++++++++++++++++----- plugins/GSdx/resource.h | 1 + 18 files changed, 371 insertions(+), 232 deletions(-) diff --git a/plugins/GSdx/GSDevice11.cpp b/plugins/GSdx/GSDevice11.cpp index 523e44d25f..4b2f012f6c 100644 --- a/plugins/GSdx/GSDevice11.cpp +++ b/plugins/GSdx/GSDevice11.cpp @@ -30,13 +30,20 @@ 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; ExShader_Compiled = false; - + 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) diff --git a/plugins/GSdx/GSDevice11.h b/plugins/GSdx/GSDevice11.h index cf40cf1609..3257bb6446 100644 --- a/plugins/GSdx/GSDevice11.h +++ b/plugins/GSdx/GSDevice11.h @@ -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 m_vs; CComPtr m_vs_cb; hash_map > m_gs; + CComPtr m_gs_cb; hash_map > m_ps; CComPtr m_ps_cb; hash_map > m_ps_ss; @@ -154,6 +158,7 @@ public: // TODO hash_map > 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); diff --git a/plugins/GSdx/GSDevice9.h b/plugins/GSdx/GSDevice9.h index 3814b4f9ea..2db03059b0 100644 --- a/plugins/GSdx/GSDevice9.h +++ b/plugins/GSdx/GSDevice9.h @@ -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); diff --git a/plugins/GSdx/GSDeviceDX.h b/plugins/GSdx/GSDeviceDX.h index e9469c8090..f75d607f1c 100644 --- a/plugins/GSdx/GSDeviceDX.h +++ b/plugins/GSdx/GSDeviceDX.h @@ -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; diff --git a/plugins/GSdx/GSRendererDX.cpp b/plugins/GSdx/GSRendererDX.cpp index 567d60af90..51589e7313 100644 --- a/plugins/GSdx/GSRendererDX.cpp +++ b/plugins/GSdx/GSRendererDX.cpp @@ -52,48 +52,48 @@ GSRendererDX::~GSRendererDX() void GSRendererDX::EmulateAtst(const int pass, const GSTextureCache::Source* tex) { - static const uint32 inverted_atst[] = { ATST_ALWAYS, ATST_NEVER, ATST_GEQUAL, ATST_GREATER, ATST_NOTEQUAL, ATST_LESS, ATST_LEQUAL, ATST_EQUAL }; + static const uint32 inverted_atst[] = {ATST_ALWAYS, ATST_NEVER, ATST_GEQUAL, ATST_GREATER, ATST_NOTEQUAL, ATST_LESS, ATST_LEQUAL, ATST_EQUAL}; int atst = (pass == 2) ? inverted_atst[m_context->TEST.ATST] : m_context->TEST.ATST; if (!m_context->TEST.ATE) return; switch (atst) { - case ATST_LESS: - if (tex && tex->m_spritehack_t) { - m_ps_sel.atst = 0; - } - else { - ps_cb.FogColor_AREF.a = (float)m_context->TEST.AREF - 0.1f; + case ATST_LESS: + if (tex && tex->m_spritehack_t) { + m_ps_sel.atst = 0; + } else { + ps_cb.FogColor_AREF.a = (float)m_context->TEST.AREF - 0.1f; + m_ps_sel.atst = 1; + } + break; + case ATST_LEQUAL: + ps_cb.FogColor_AREF.a = (float)m_context->TEST.AREF - 0.1f + 1.0f; m_ps_sel.atst = 1; - } - break; - case ATST_LEQUAL: - ps_cb.FogColor_AREF.a = (float)m_context->TEST.AREF - 0.1f + 1.0f; - m_ps_sel.atst = 1; - break; - case ATST_GEQUAL: - // Maybe a -1 trick multiplication factor could be used to merge with ATST_LEQUAL case - ps_cb.FogColor_AREF.a = (float)m_context->TEST.AREF - 0.1f; - m_ps_sel.atst = 2; - break; - case ATST_GREATER: - // Maybe a -1 trick multiplication factor could be used to merge with ATST_LESS case - ps_cb.FogColor_AREF.a = (float)m_context->TEST.AREF - 0.1f + 1.0f; - m_ps_sel.atst = 2; - break; - case ATST_EQUAL: - ps_cb.FogColor_AREF.a = (float)m_context->TEST.AREF; - m_ps_sel.atst = 3; - break; - case ATST_NOTEQUAL: - ps_cb.FogColor_AREF.a = (float)m_context->TEST.AREF; - m_ps_sel.atst = 4; - break; - case ATST_NEVER: - case ATST_ALWAYS: - default: - m_ps_sel.atst = 0; - break; + break; + case ATST_GEQUAL: + // Maybe a -1 trick multiplication factor could be used to merge with ATST_LEQUAL case + ps_cb.FogColor_AREF.a = (float)m_context->TEST.AREF - 0.1f; + m_ps_sel.atst = 2; + break; + case ATST_GREATER: + // Maybe a -1 trick multiplication factor could be used to merge with ATST_LESS case + ps_cb.FogColor_AREF.a = (float)m_context->TEST.AREF - 0.1f + 1.0f; + m_ps_sel.atst = 2; + break; + case ATST_EQUAL: + ps_cb.FogColor_AREF.a = (float)m_context->TEST.AREF; + m_ps_sel.atst = 3; + break; + case ATST_NOTEQUAL: + ps_cb.FogColor_AREF.a = (float)m_context->TEST.AREF; + m_ps_sel.atst = 4; + break; + + 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; + break; } } @@ -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 diff --git a/plugins/GSdx/GSRendererDX.h b/plugins/GSdx/GSRendererDX.h index da8cd7e3df..e695ae3d00 100644 --- a/plugins/GSdx/GSRendererDX.h +++ b/plugins/GSdx/GSRendererDX.h @@ -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)); diff --git a/plugins/GSdx/GSRendererDX11.cpp b/plugins/GSdx/GSRendererDX11.cpp index 34172b2b89..0f947bda40 100644 --- a/plugins/GSdx/GSRendererDX11.cpp +++ b/plugins/GSdx/GSRendererDX11.cpp @@ -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); } diff --git a/plugins/GSdx/GSRendererDX11.h b/plugins/GSdx/GSRendererDX11.h index 53d1021222..d3d27d2bc0 100644 --- a/plugins/GSdx/GSRendererDX11.h +++ b/plugins/GSdx/GSRendererDX11.h @@ -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(); diff --git a/plugins/GSdx/GSRendererDX9.cpp b/plugins/GSdx/GSRendererDX9.cpp index aba27de2f6..761f447bda 100644 --- a/plugins/GSdx/GSRendererDX9.cpp +++ b/plugins/GSdx/GSRendererDX9.cpp @@ -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; diff --git a/plugins/GSdx/GSRendererDX9.h b/plugins/GSdx/GSRendererDX9.h index c7e3b8c8b2..817abed5cd 100644 --- a/plugins/GSdx/GSRendererDX9.h +++ b/plugins/GSdx/GSRendererDX9.h @@ -34,7 +34,7 @@ protected: Direct3DBlendState9 bs; } m_fba; - void SetupIA(); + void SetupIA(const float& sx, const float& sy); void UpdateFBA(GSTexture* rt); public: diff --git a/plugins/GSdx/GSRendererHW.cpp b/plugins/GSdx/GSRendererHW.cpp index 8b8c980925..f51bb6dca0 100644 --- a/plugins/GSdx/GSRendererHW.cpp +++ b/plugins/GSdx/GSRendererHW.cpp @@ -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); diff --git a/plugins/GSdx/GSRendererHW.h b/plugins/GSdx/GSRendererHW.h index 9f1d98c499..03053bbdcd 100644 --- a/plugins/GSdx/GSRendererHW.h +++ b/plugins/GSdx/GSRendererHW.h @@ -167,6 +167,7 @@ public: GSVector2i GetCustomResolution(); void SetScaling(); GSVector4 RealignTargetTextureCoordinate(const GSTextureCache::Source* tex); + void Lines2Sprites(); void Reset(); void VSync(int field); diff --git a/plugins/GSdx/GSRendererOGL.cpp b/plugins/GSdx/GSRendererOGL.cpp index fc74522812..fc3095b1df 100644 --- a/plugins/GSdx/GSRendererOGL.cpp +++ b/plugins/GSdx/GSRendererOGL.cpp @@ -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) { diff --git a/plugins/GSdx/GSRendererOGL.h b/plugins/GSdx/GSRendererOGL.h index 29f3f55d6f..39b2c109d0 100644 --- a/plugins/GSdx/GSRendererOGL.h +++ b/plugins/GSdx/GSRendererOGL.h @@ -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); diff --git a/plugins/GSdx/GSSettingsDlg.cpp b/plugins/GSdx/GSSettingsDlg.cpp index 8e4ae31f8c..82ed512fbe 100644 --- a/plugins/GSdx/GSSettingsDlg.cpp +++ b/plugins/GSdx/GSSettingsDlg.cpp @@ -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); diff --git a/plugins/GSdx/GSTextureFX11.cpp b/plugins/GSdx/GSTextureFX11.cpp index 4e83785dbb..56d14abec3 100644 --- a/plugins/GSdx/GSTextureFX11.cpp +++ b/plugins/GSdx/GSTextureFX11.cpp @@ -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 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 >::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) diff --git a/plugins/GSdx/res/tfx.fx b/plugins/GSdx/res/tfx.fx index 4fcc670dc6..ebf3c53f19 100644 --- a/plugins/GSdx/res/tfx.fx +++ b/plugins/GSdx/res/tfx.fx @@ -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 stream) @@ -638,19 +645,104 @@ void gs_main(point VS_OUTPUT input[1], inout PointStream 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 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 stream) { - #if GS_IIP == 0 +#if GS_IIP == 0 input[0].c = input[1].c; - #endif +#endif stream.Append(input[0]); stream.Append(input[1]); } +#elif GS_PRIM == 1 && GS_LINE == 1 + +[maxvertexcount(6)] +void gs_main(line VS_OUTPUT input[2], inout TriangleStream 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 stream [maxvertexcount(4)] void gs_main(line VS_OUTPUT input[2], inout TriangleStream 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 diff --git a/plugins/GSdx/resource.h b/plugins/GSdx/resource.h index 165a7011f5..04e3f66f49 100644 --- a/plugins/GSdx/resource.h +++ b/plugins/GSdx/resource.h @@ -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