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