1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

Added bicubic display filter

This commit is contained in:
narzoul 2023-03-12 16:22:41 +01:00
parent 3627af8d37
commit b377102d8d
8 changed files with 59 additions and 11 deletions

View File

@ -8,6 +8,7 @@ namespace Config
: MappedSetting("DisplayFilter", "bilinear", {
{"point", POINT},
{"bilinear", BILINEAR},
{"bicubic", BICUBIC},
{"lanczos", LANCZOS},
})
{
@ -18,6 +19,7 @@ namespace Config
switch (m_value)
{
case BILINEAR:
case BICUBIC:
return { "Blur", 0, 100, 0, m_param };
case LANCZOS:
return { "Lobes", 2, 4, 2, m_param };

View File

@ -11,7 +11,8 @@ namespace Config
public:
static const UINT POINT = 0;
static const UINT BILINEAR = 1;
static const UINT LANCZOS = 2;
static const UINT BICUBIC = 2;
static const UINT LANCZOS = 3;
DisplayFilter();

View File

@ -7,6 +7,7 @@
#include <D3dDdi/ShaderBlitter.h>
#include <D3dDdi/SurfaceRepository.h>
#include <DDraw/Surfaces/PrimarySurface.h>
#include <Shaders/Bicubic.h>
#include <Shaders/ColorKey.h>
#include <Shaders/ColorKeyBlend.h>
#include <Shaders/DepthBlt.h>
@ -57,6 +58,7 @@ 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_psDepthBlt(createPixelShader(g_psDepthBlt))
@ -68,6 +70,8 @@ namespace D3dDdi
, m_psPaletteLookup(createPixelShader(g_psPaletteLookup))
, m_psTextureSampler(createPixelShader(g_psTextureSampler))
, m_vertexShaderDecl(createVertexShaderDecl())
, m_convolutionBaseParams{}
, m_convolutionExtraParams{}
, m_vertices{}
{
for (std::size_t i = 0; i < m_vertices.size(); ++i)
@ -76,6 +80,22 @@ namespace D3dDdi
}
}
void ShaderBlitter::bicubicBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, UINT blurPercent)
{
LOG_FUNC("ShaderBlitter::bicubicBlt", static_cast<HANDLE>(dstResource), dstSubResourceIndex, dstRect,
static_cast<HANDLE>(srcResource), srcSubResourceIndex, srcRect, blurPercent);
const float B = blurPercent / 100.0f;
const float C = (1 - B) / 2;
m_convolutionExtraParams[0] = { (12 - 9 * B - 6 * C) / 6, (-18 + 12 * B + 6 * C) / 6, 0, (6 - 2 * B) / 6 };
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());
}
void ShaderBlitter::blt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
HANDLE pixelShader, UINT filter, UINT flags, const BYTE* alpha, const Gdi::Region& srcRgn)
@ -192,23 +212,23 @@ namespace D3dDdi
const float firstKernelOffset = firstSampleOffset * kernelStep;
const float firstTextureOffset = firstSampleOffset * textureStep;
std::array<DeviceState::ShaderConstF, 5> reg = {};
reg[0] = { textureSize.x, textureSize.y, textureSizeRcp.x, textureSizeRcp.y };
m_convolutionBaseParams[0] = { textureSize.x, textureSize.y, textureSizeRcp.x, textureSizeRcp.y };
if (isHorizontal)
{
reg[1] = { firstTextureOffset, 0, firstKernelOffset, 0 };
reg[2] = { textureStep, 0, kernelStep, 0 };
reg[3] = { -0.5f, 0, 0.5f * textureSizeRcp.x, 0.5f * textureSizeRcp.y };
m_convolutionBaseParams[1] = { firstTextureOffset, 0, firstKernelOffset, 0 };
m_convolutionBaseParams[2] = { textureStep, 0, kernelStep, 0 };
m_convolutionBaseParams[3] = { -0.5f, 0, 0.5f * textureSizeRcp.x, 0.5f * textureSizeRcp.y };
}
else
{
reg[1] = { 0, firstTextureOffset, 0, firstKernelOffset };
reg[2] = { 0, textureStep, 0, kernelStep };
reg[3] = { 0, -0.5f, 0.5f * textureSizeRcp.x, 0.5f * textureSizeRcp.y };
m_convolutionBaseParams[1] = { 0, firstTextureOffset, 0, firstKernelOffset };
m_convolutionBaseParams[2] = { 0, textureStep, 0, kernelStep };
m_convolutionBaseParams[3] = { 0, -0.5f, 0.5f * textureSizeRcp.x, 0.5f * textureSizeRcp.y };
}
reg[4] = { support, 1.0f / support, 0, 0 };
m_convolutionBaseParams[4] = { support, 1.0f / support, 0, 0 };
DeviceState::TempPixelShaderConst tempPsConst(m_device.getState(), { 0, reg.size() }, reg.data());
DeviceState::TempPixelShaderConst tempPsConst(m_device.getState(),
{ 0, m_convolutionBaseParams.size() + m_convolutionExtraParams.size()}, m_convolutionBaseParams.data());
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
pixelShader, D3DTEXF_LINEAR | D3DTEXF_SRGB);
}
@ -470,6 +490,11 @@ namespace D3dDdi
srcResource, srcSubResourceIndex, srcRect, Config::displayFilter.getParam());
break;
case Config::Settings::DisplayFilter::BICUBIC:
m_device.getShaderBlitter().bicubicBlt(rt, rtIndex, rtRect,
srcResource, srcSubResourceIndex, srcRect, Config::displayFilter.getParam());
break;
case Config::Settings::DisplayFilter::LANCZOS:
m_device.getShaderBlitter().lanczosBlt(rt, rtIndex, rtRect,
srcResource, srcSubResourceIndex, srcRect, Config::displayFilter.getParam());

View File

@ -25,6 +25,8 @@ namespace D3dDdi
ShaderBlitter& operator=(const ShaderBlitter&) = delete;
ShaderBlitter& operator=(ShaderBlitter&&) = delete;
void bicubicBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, UINT blurPercent);
void colorKeyBlt(const Resource& dstResource, UINT dstSubResourceIndex,
const Resource& srcResource, UINT srcSubResourceIndex, DeviceState::ShaderConstF srcColorKey);
void cursorBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
@ -86,6 +88,7 @@ namespace D3dDdi
void setTextureCoords(UINT stage, const RECT& rect, UINT width, UINT height);
Device& m_device;
std::unique_ptr<void, ResourceDeleter> m_psBicubic;
std::unique_ptr<void, ResourceDeleter> m_psColorKey;
std::unique_ptr<void, ResourceDeleter> m_psColorKeyBlend;
std::unique_ptr<void, ResourceDeleter> m_psDepthBlt;
@ -97,6 +100,8 @@ namespace D3dDdi
std::unique_ptr<void, ResourceDeleter> m_psPaletteLookup;
std::unique_ptr<void, ResourceDeleter> m_psTextureSampler;
std::unique_ptr<void, ResourceDeleter> m_vertexShaderDecl;
std::array<DeviceState::ShaderConstF, 5> m_convolutionBaseParams;
std::array<DeviceState::ShaderConstF, 2> m_convolutionExtraParams;
std::array<Vertex, 4> m_vertices;
};
}

View File

@ -460,6 +460,7 @@
<None Include="Shaders\Convolution.hlsli" />
</ItemGroup>
<ItemGroup>
<FxCompile Include="Shaders\Bicubic.hlsl" />
<FxCompile Include="Shaders\ColorKey.hlsl" />
<FxCompile Include="Shaders\ColorKeyBlend.hlsl" />
<FxCompile Include="Shaders\DepthBlt.hlsl" />

View File

@ -1103,6 +1103,9 @@
<FxCompile Include="Shaders\Lanczos.hlsl">
<Filter>Shaders</Filter>
</FxCompile>
<FxCompile Include="Shaders\Bicubic.hlsl">
<Filter>Shaders</Filter>
</FxCompile>
</ItemGroup>
<ItemGroup>
<Image Include="arrow.bmp">

View File

@ -0,0 +1,9 @@
#include "Convolution.hlsli"
float kernel(float x)
{
x = min(abs(x), g_support);
const float4 weights = x < 1 ? g_extraParams[0] : g_extraParams[1];
const float4 powers = float4(pow(x, 3), pow(x, 2), x, 1);
return dot(weights, powers);
}

View File

@ -3,6 +3,8 @@ int g_sampleCountX : register(i0);
int g_sampleCountY : register(i1);
float4 c[32] : register(c0);
float4 g_extraParams[2] : register(c5);
static const float2 g_textureSize = c[0].xy;
static const float2 g_textureSizeRcp = c[0].zw;
static const float4 g_firstCoordOffset = c[1];