diff --git a/DDrawCompat/Config/Settings/DisplayFilter.cpp b/DDrawCompat/Config/Settings/DisplayFilter.cpp index b69fc62..84273d8 100644 --- a/DDrawCompat/Config/Settings/DisplayFilter.cpp +++ b/DDrawCompat/Config/Settings/DisplayFilter.cpp @@ -10,6 +10,7 @@ namespace Config {"bilinear", BILINEAR}, {"bicubic", BICUBIC}, {"lanczos", LANCZOS}, + {"spline", SPLINE} }) { } @@ -22,6 +23,7 @@ namespace Config case BICUBIC: return { "Blur", 0, 100, 0, m_param }; case LANCZOS: + case SPLINE: return { "Lobes", 2, 4, 2, m_param }; default: return {}; diff --git a/DDrawCompat/Config/Settings/DisplayFilter.h b/DDrawCompat/Config/Settings/DisplayFilter.h index 28648e5..ee3f57f 100644 --- a/DDrawCompat/Config/Settings/DisplayFilter.h +++ b/DDrawCompat/Config/Settings/DisplayFilter.h @@ -13,6 +13,7 @@ namespace Config static const UINT BILINEAR = 1; static const UINT BICUBIC = 2; static const UINT LANCZOS = 3; + static const UINT SPLINE = 4; DisplayFilter(); diff --git a/DDrawCompat/D3dDdi/ShaderBlitter.cpp b/DDrawCompat/D3dDdi/ShaderBlitter.cpp index be5691b..e0c77e2 100644 --- a/DDrawCompat/D3dDdi/ShaderBlitter.cpp +++ b/DDrawCompat/D3dDdi/ShaderBlitter.cpp @@ -7,9 +7,11 @@ #include #include #include -#include #include #include +#include +#include +#include #include #include #include @@ -45,6 +47,16 @@ namespace return ck; } + constexpr D3dDdi::DeviceState::ShaderConstF getSplineWeights(int n, float a, float b, float c, float d) + { + return { + a, + -3 * n * a + b, + 3 * n * n * a - 2 * n * b + c, + -n * n * n * a + n * n * b - n * c + d + }; + } + void setGammaValues(BYTE* ptr, USHORT* ramp) { for (UINT i = 0; i < 256; ++i) @@ -58,9 +70,13 @@ namespace D3dDdi { ShaderBlitter::ShaderBlitter(Device& device) : m_device(device) - , m_psBicubic(createPixelShader(g_psBicubic)) , m_psColorKey(createPixelShader(g_psColorKey)) , m_psColorKeyBlend(createPixelShader(g_psColorKeyBlend)) + , m_psCubicConvolution{ + createPixelShader(g_psCubicConvolution2), + createPixelShader(g_psCubicConvolution3), + createPixelShader(g_psCubicConvolution4) + } , m_psDepthBlt(createPixelShader(g_psDepthBlt)) , m_psDrawCursor(createPixelShader(g_psDrawCursor)) , m_psGamma(createPixelShader(g_psGamma)) @@ -93,7 +109,7 @@ namespace D3dDdi m_convolutionExtraParams[1] = { (-B - 6 * C) / 6, (6 * B + 30 * C) / 6, (-12 * B - 48 * C) / 6, (8 * B + 24 * C) / 6 }; convolutionBlt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect, - 2, m_psBicubic.get()); + 2, m_psCubicConvolution[0].get()); } void ShaderBlitter::blt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect, @@ -499,6 +515,11 @@ namespace D3dDdi m_device.getShaderBlitter().lanczosBlt(rt, rtIndex, rtRect, srcResource, srcSubResourceIndex, srcRect, Config::displayFilter.getParam()); break; + + case Config::Settings::DisplayFilter::SPLINE: + m_device.getShaderBlitter().splineBlt(rt, rtIndex, rtRect, + srcResource, srcSubResourceIndex, srcRect, Config::displayFilter.getParam()); + break; } if (rtGamma) @@ -691,6 +712,37 @@ namespace D3dDdi m_vertices[3].tc[stage] = { rect.right / w, rect.bottom / h }; } + void ShaderBlitter::splineBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect, + const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, UINT lobes) + { + LOG_FUNC("ShaderBlitter::splineBlt", static_cast(dstResource), dstSubResourceIndex, dstRect, + static_cast(srcResource), srcSubResourceIndex, srcRect, lobes); + + switch (lobes) + { + case 2: + m_convolutionExtraParams[0] = getSplineWeights(0, 1.0f, -9.0f / 5.0f, -1.0f / 5.0f, 1.0f); + m_convolutionExtraParams[1] = getSplineWeights(1, -1.0f / 3.0f, 4.0f / 5.0f, -7.0f / 15.0f, 0.0f); + break; + + case 3: + m_convolutionExtraParams[0] = getSplineWeights(0, 13.0f / 11.0f, -453.0f / 209.0f, -3.0f / 209.0f, 1.0f); + m_convolutionExtraParams[1] = getSplineWeights(1, -6.0f / 11.0f, 270.0f / 209.0f, -156.0f / 209.0f, 0.0f); + m_convolutionExtraParams[2] = getSplineWeights(2, 1.0f / 11.0f, -45.0f / 209.0f, 26.0f / 209.0f, 0.0f); + break; + + case 4: + m_convolutionExtraParams[0] = getSplineWeights(0, 49.0f / 41.0f, -6387.0f / 2911.0f, -3.0f / 2911.0f, 1.0f); + m_convolutionExtraParams[1] = getSplineWeights(1, -24.0f / 41.0f, 4032.0f / 2911.0f, -2328.0f / 2911.0f, 0.0f); + m_convolutionExtraParams[2] = getSplineWeights(2, 6.0f / 41.0f, -1008.0f / 2911.0f, 582.0f / 2911.0f, 0.0f); + m_convolutionExtraParams[3] = getSplineWeights(3, -1.0f / 41.0f, 168.0f / 2911.0f, -97.0f / 2911.0f, 0.0f); + break; + } + + convolutionBlt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect, + lobes, m_psCubicConvolution[lobes - 2].get()); + } + void ShaderBlitter::textureBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect, const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, UINT filter, const DeviceState::ShaderConstF* srcColorKey, const BYTE* alpha, const Gdi::Region& srcRgn) diff --git a/DDrawCompat/D3dDdi/ShaderBlitter.h b/DDrawCompat/D3dDdi/ShaderBlitter.h index f578bf4..fb78a03 100644 --- a/DDrawCompat/D3dDdi/ShaderBlitter.h +++ b/DDrawCompat/D3dDdi/ShaderBlitter.h @@ -46,6 +46,8 @@ namespace D3dDdi const Resource& lockRefResource); void palettizedBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect, const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, RGBQUAD palette[256]); + void splineBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect, + const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, UINT lobes); void textureBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect, const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, UINT filter, const DeviceState::ShaderConstF* srcColorKey = nullptr, const BYTE* alpha = nullptr, @@ -88,9 +90,9 @@ namespace D3dDdi void setTextureCoords(UINT stage, const RECT& rect, UINT width, UINT height); Device& m_device; - std::unique_ptr m_psBicubic; std::unique_ptr m_psColorKey; std::unique_ptr m_psColorKeyBlend; + std::unique_ptr m_psCubicConvolution[3]; std::unique_ptr m_psDepthBlt; std::unique_ptr m_psDrawCursor; std::unique_ptr m_psGamma; @@ -101,7 +103,7 @@ namespace D3dDdi std::unique_ptr m_psTextureSampler; std::unique_ptr m_vertexShaderDecl; std::array m_convolutionBaseParams; - std::array m_convolutionExtraParams; + std::array m_convolutionExtraParams; std::array m_vertices; }; } diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj index c98a678..bd9f10d 100644 --- a/DDrawCompat/DDrawCompat.vcxproj +++ b/DDrawCompat/DDrawCompat.vcxproj @@ -458,11 +458,14 @@ + - + + + diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters index 94b4300..1855105 100644 --- a/DDrawCompat/DDrawCompat.vcxproj.filters +++ b/DDrawCompat/DDrawCompat.vcxproj.filters @@ -1068,6 +1068,9 @@ Shaders + + Shaders + @@ -1103,7 +1106,13 @@ Shaders - + + Shaders + + + Shaders + + Shaders diff --git a/DDrawCompat/Shaders/Convolution.hlsli b/DDrawCompat/Shaders/Convolution.hlsli index 3c9d836..7c8c477 100644 --- a/DDrawCompat/Shaders/Convolution.hlsli +++ b/DDrawCompat/Shaders/Convolution.hlsli @@ -3,7 +3,7 @@ int g_sampleCountX : register(i0); int g_sampleCountY : register(i1); float4 c[32] : register(c0); -float4 g_extraParams[2] : register(c5); +float4 g_extraParams[4] : register(c5); static const float2 g_textureSize = c[0].xy; static const float2 g_textureSizeRcp = c[0].zw; diff --git a/DDrawCompat/Shaders/Bicubic.hlsl b/DDrawCompat/Shaders/CubicConvolution.hlsli similarity index 52% rename from DDrawCompat/Shaders/Bicubic.hlsl rename to DDrawCompat/Shaders/CubicConvolution.hlsli index 5a912b0..0ad8bdc 100644 --- a/DDrawCompat/Shaders/Bicubic.hlsl +++ b/DDrawCompat/Shaders/CubicConvolution.hlsli @@ -3,7 +3,16 @@ float kernel(float x) { x = min(abs(x), g_support); - const float4 weights = x < 1 ? g_extraParams[0] : g_extraParams[1]; + + float4 weights = g_extraParams[LOBES - 1]; + [unroll] for (int i = LOBES - 1; i != 0; --i) + { + if (x < i) + { + weights = g_extraParams[i - 1]; + } + } + const float4 powers = float4(pow(x, 3), pow(x, 2), x, 1); return dot(weights, powers); } diff --git a/DDrawCompat/Shaders/CubicConvolution2.hlsl b/DDrawCompat/Shaders/CubicConvolution2.hlsl new file mode 100644 index 0000000..ba175aa --- /dev/null +++ b/DDrawCompat/Shaders/CubicConvolution2.hlsl @@ -0,0 +1,3 @@ +static const int LOBES = 2; + +#include "CubicConvolution.hlsli" diff --git a/DDrawCompat/Shaders/CubicConvolution3.hlsl b/DDrawCompat/Shaders/CubicConvolution3.hlsl new file mode 100644 index 0000000..39c27ea --- /dev/null +++ b/DDrawCompat/Shaders/CubicConvolution3.hlsl @@ -0,0 +1,3 @@ +static const int LOBES = 3; + +#include "CubicConvolution.hlsli" diff --git a/DDrawCompat/Shaders/CubicConvolution4.hlsl b/DDrawCompat/Shaders/CubicConvolution4.hlsl new file mode 100644 index 0000000..107d301 --- /dev/null +++ b/DDrawCompat/Shaders/CubicConvolution4.hlsl @@ -0,0 +1,3 @@ +static const int LOBES = 4; + +#include "CubicConvolution.hlsli"