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

Added dithered RenderColorDepth values

This commit is contained in:
narzoul 2023-11-02 00:23:22 +01:00
parent 7019ea18c9
commit 144dab2538
17 changed files with 412 additions and 180 deletions

View File

@ -6,11 +6,20 @@ namespace Config
{
namespace Settings
{
class RenderColorDepth : public MappedSetting<unsigned>
class RenderColorDepth : public MappedSetting<std::pair<unsigned, unsigned>>
{
public:
RenderColorDepth()
: MappedSetting("RenderColorDepth", "app", { {"app", 0}, {"16", 16}, {"32", 32} })
: MappedSetting("RenderColorDepth", "appd8", {
{ "app", { 0, 8 } },
{ "appd8", { 8, 0 } },
{ "appd10", { 10, 0 } },
{ "16", { 6, 8 } },
{ "16d8", { 8, 6 } },
{ "16d10", { 10, 6 } },
{ "32", { 8, 8 } },
{ "32d10", { 10, 8 } },
})
{
}
};

View File

@ -8,6 +8,7 @@
#include <Config/Settings/Antialiasing.h>
#include <Config/Settings/DisplayAspectRatio.h>
#include <Config/Settings/PalettizedTextures.h>
#include <Config/Settings/RenderColorDepth.h>
#include <Config/Settings/ResolutionScale.h>
#include <Config/Settings/SupportedDepthFormats.h>
#include <D3dDdi/Adapter.h>
@ -226,6 +227,41 @@ namespace D3dDdi
return { levels.MsType, std::min(static_cast<UINT>(Config::antialiasing.getParam()), levels.QualityLevels - 1) };
}
D3DDDIFORMAT Adapter::getRenderColorDepthSrcFormat(D3DDDIFORMAT appFormat) const
{
switch (Config::renderColorDepth.get().first)
{
case 10:
if (isSupportedRttFormat(D3DDDIFMT_A2B10G10R10))
{
return D3DDDIFMT_A2B10G10R10;
}
if (isSupportedRttFormat(D3DDDIFMT_A2R10G10B10))
{
return D3DDDIFMT_A2R10G10B10;
}
[[fallthrough]];
case 8:
return D3DDDIFMT_X8R8G8B8;
case 6:
return D3DDDIFMT_R5G6B5;
}
return appFormat;
}
D3DDDIFORMAT Adapter::getRenderColorDepthDstFormat() const
{
switch (Config::renderColorDepth.get().second)
{
case 6: return D3DDDIFMT_R5G6B5;
case 8: return D3DDDIFMT_X8R8G8B8;
}
return 16 == Win32::DisplayMode::getBpp() ? D3DDDIFMT_R5G6B5 : D3DDDIFMT_X8R8G8B8;
}
SIZE Adapter::getScaledSize(Int2 size) const
{
const auto scaleFactor = getScaleFactor();
@ -349,6 +385,14 @@ namespace D3dDdi
return it != formatOps.end() && (it->second.Operations & FORMATOP_OFFSCREEN_RENDERTARGET);
}
bool Adapter::isSupportedRttFormat(D3DDDIFORMAT format) const
{
auto it = m_info.formatOps.find(format);
return it != m_info.formatOps.end() &&
(it->second.Format & FORMATOP_OFFSCREEN_RENDERTARGET) &&
(it->second.Format & FORMATOP_TEXTURE);
}
HRESULT Adapter::pfnCloseAdapter()
{
auto adapter = m_adapter;

View File

@ -41,6 +41,8 @@ namespace D3dDdi
const auto& getMonitorInfo() const { return Win32::DisplayMode::getMonitorInfo(m_deviceName); }
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> getMultisampleConfig(D3DDDIFORMAT format) const;
const D3DDDI_ADAPTERFUNCS& getOrigVtable() const { return m_origVtable; }
D3DDDIFORMAT getRenderColorDepthSrcFormat(D3DDDIFORMAT appFormat) const;
D3DDDIFORMAT getRenderColorDepthDstFormat() const;
CompatWeakPtr<IDirectDraw7> getRepository() const { return m_repository; }
SIZE getScaledSize(Int2 size) const;
bool isEmulatedRenderTargetFormat(D3DDDIFORMAT format) const;
@ -66,6 +68,7 @@ namespace D3dDdi
std::string getSupportedMsaaModes(const std::map<D3DDDIFORMAT, FORMATOP>& formatOps) const;
DWORD getSupportedZBufferBitDepths(const std::map<D3DDDIFORMAT, FORMATOP>& formatOps) const;
bool isEmulatedRenderTargetFormat(D3DDDIFORMAT format, const std::map<D3DDDIFORMAT, FORMATOP>& formatOps) const;
bool isSupportedRttFormat(D3DDDIFORMAT format) const;
HANDLE m_adapter;
D3DDDI_ADAPTERFUNCS m_origVtable;

View File

@ -48,6 +48,20 @@ namespace D3dDdi
m_state.m_device, &m_data, &m_state.m_pixelShaderConst[m_data.Register][0]);
}
DeviceState::TempPixelShaderConstB::TempPixelShaderConstB(
DeviceState& state, const D3DDDIARG_SETPIXELSHADERCONSTB& data, const BOOL* registers)
: m_state(state)
, m_data(data)
{
state.m_device.getOrigVtable().pfnSetPixelShaderConstB(state.m_device, &data, registers);
}
DeviceState::TempPixelShaderConstB::~TempPixelShaderConstB()
{
m_state.m_device.getOrigVtable().pfnSetPixelShaderConstB(
m_state.m_device, &m_data, &m_state.m_pixelShaderConstB[m_data.Register][0]);
}
DeviceState::TempPixelShaderConstI::TempPixelShaderConstI(
DeviceState& state, const D3DDDIARG_SETPIXELSHADERCONSTI& data, const ShaderConstI* registers)
: m_state(state)

View File

@ -15,7 +15,9 @@ const UINT D3DTEXF_NONE = 0;
const UINT D3DTEXF_POINT = 1;
const UINT D3DTEXF_LINEAR = 2;
const UINT D3DTEXF_ANISOTROPIC = 3;
const UINT D3DTEXF_SRGB = 0x10000;
const UINT D3DTEXF_SRGBREAD = 0x10000;
const UINT D3DTEXF_SRGBWRITE = 0x20000;
const UINT D3DTEXF_SRGB = D3DTEXF_SRGBREAD | D3DTEXF_SRGBWRITE;
namespace D3dDdi
{
@ -59,6 +61,17 @@ namespace D3dDdi
D3DDDIARG_SETPIXELSHADERCONST m_data;
};
class TempPixelShaderConstB
{
public:
TempPixelShaderConstB(DeviceState& state, const D3DDDIARG_SETPIXELSHADERCONSTB& data, const BOOL* registers);
~TempPixelShaderConstB();
private:
DeviceState& m_state;
D3DDDIARG_SETPIXELSHADERCONSTB m_data;
};
class TempPixelShaderConstI
{
public:

View File

@ -109,8 +109,10 @@ namespace
{ D3DDDIFMT_A8R3G3B2, FormatInfoXARGB(0, 8, 3, 3, 2) },
{ D3DDDIFMT_X4R4G4B4, FormatInfoXARGB(4, 0, 4, 4, 4) },
{ D3DDDIFMT_A8B8G8R8, FormatInfoXABGR(0, 8, 8, 8, 8) },
{ D3DDDIFMT_X8B8G8R8, FormatInfoXABGR(8, 0, 8, 8, 8) },
{ D3DDDIFMT_A2B10G10R10, FormatInfoXABGR(0, 2, 10, 10, 10) },
{ D3DDDIFMT_A8B8G8R8, FormatInfoXABGR(0, 8, 8, 8, 8) },
{ D3DDDIFMT_X8B8G8R8, FormatInfoXABGR(8, 0, 8, 8, 8) },
{ D3DDDIFMT_A2R10G10B10, FormatInfoXARGB(0, 2, 10, 10, 10) },
{ D3DDDIFMT_A8P8, FormatInfoAP(8, 8) },
{ D3DDDIFMT_P8, FormatInfoAP(0, 8) },
@ -141,6 +143,11 @@ namespace
DDPIXELFORMAT getPixelFormat(const D3dDdi::FormatInfo& info)
{
if (info.red.bitCount > 8)
{
return {};
}
DDPIXELFORMAT pf = {};
pf.dwSize = sizeof(pf);
pf.dwFlags =

View File

@ -8,7 +8,6 @@
#include <Config/Settings/BltFilter.h>
#include <Config/Settings/ColorKeyMethod.h>
#include <Config/Settings/DepthFormat.h>
#include <Config/Settings/RenderColorDepth.h>
#include <Config/Settings/ResolutionScaleFilter.h>
#include <D3dDdi/Adapter.h>
#include <D3dDdi/Device.h>
@ -529,6 +528,12 @@ namespace D3dDdi
srcResource, subResourceIndex, getRect(subResourceIndex));
}
HRESULT Resource::copySubResourceRegion(UINT dstIndex, const RECT& dstRect,
HANDLE src, UINT srcIndex, const RECT& srcRect)
{
return copySubResourceRegion(*this, dstIndex, dstRect, src, srcIndex, srcRect);
}
HRESULT Resource::copySubResourceRegion(HANDLE dst, UINT dstIndex, const RECT& dstRect,
HANDLE src, UINT srcIndex, const RECT& srcRect)
{
@ -743,11 +748,7 @@ namespace D3dDdi
if (D3DDDIFMT_X8R8G8B8 == m_fixedData.Format || D3DDDIFMT_R5G6B5 == m_fixedData.Format)
{
switch (Config::renderColorDepth.get())
{
case 16: return D3DDDIFMT_R5G6B5;
case 32: return D3DDDIFMT_X8R8G8B8;
}
return m_device.getAdapter().getRenderColorDepthSrcFormat(m_fixedData.Format);
}
else if (m_fixedData.Flags.ZBuffer && Config::Settings::DepthFormat::APP != Config::depthFormat.get() &&
getFormatInfo(m_fixedData.Format).depth.bitCount != Config::depthFormat.get())
@ -1212,7 +1213,7 @@ namespace D3dDdi
}
auto& repo = m_device.getRepo();
const auto& rtSurface = repo.getNextRenderTarget(srcWidth, srcHeight);
const auto& rtSurface = repo.getNextRenderTarget(srcWidth, srcHeight, srcResource->m_fixedData.Format);
auto rt = rtSurface.resource ? rtSurface.resource : this;
auto rtIndex = rtSurface.resource ? 0 : data.DstSubResourceIndex;
auto rtRect = rtSurface.resource ? data.SrcRect : data.DstRect;
@ -1259,15 +1260,12 @@ namespace D3dDdi
m_device.getShaderBlitter().cursorBlt(*rt, rtIndex, rtRect, cursorInfo.hCursor, cursorInfo.ptScreenPos);
}
if (!rtSurface.resource)
if (rtSurface.resource)
{
return LOG_RESULT(S_OK);
m_device.getShaderBlitter().displayBlt(*this, data.DstSubResourceIndex, data.DstRect, *rt, 0, data.SrcRect);
clearRectExterior(data.DstSubResourceIndex, data.DstRect);
}
m_device.getShaderBlitter().displayBlt(*this, data.DstSubResourceIndex, data.DstRect, *rt, 0, data.SrcRect);
clearRectExterior(data.DstSubResourceIndex, data.DstRect);
if (!IsRectEmpty(&g_presentationRect))
{
presentLayeredWindows(*this, data.DstSubResourceIndex, getRect(data.DstSubResourceIndex),
@ -1468,7 +1466,7 @@ namespace D3dDdi
if (!srcResource.m_fixedData.Flags.Texture ||
D3DDDIPOOL_SYSTEMMEM == srcResource.m_fixedData.Pool ||
(filter & D3DTEXF_SRGB) && !(srcResource.m_formatOp.Operations & FORMATOP_SRGBREAD))
(filter & D3DTEXF_SRGBREAD) && !(srcResource.m_formatOp.Operations & FORMATOP_SRGBREAD))
{
DWORD width = data.SrcRect.right - data.SrcRect.left;
DWORD height = data.SrcRect.bottom - data.SrcRect.top;
@ -1498,11 +1496,11 @@ namespace D3dDdi
}
if (!dstResource.m_fixedData.Flags.RenderTarget && !dstResource.m_fixedData.Flags.ZBuffer ||
(filter & D3DTEXF_SRGB) && !(dstResource.m_formatOp.Operations & FORMATOP_SRGBWRITE))
(filter & D3DTEXF_SRGBWRITE) && !(dstResource.m_formatOp.Operations & FORMATOP_SRGBWRITE))
{
LONG width = data.DstRect.right - data.DstRect.left;
LONG height = data.DstRect.bottom - data.DstRect.top;
auto& rt = repo.getNextRenderTarget(width, height, srcRes);
auto& rt = repo.getNextRenderTarget(width, height, D3DDDIFMT_X8R8G8B8, srcRes);
if (!rt.resource)
{
return LOG_RESULT(E_OUTOFMEMORY);

View File

@ -39,6 +39,8 @@ namespace D3dDdi
HRESULT blt(D3DDDIARG_BLT data);
HRESULT colorFill(D3DDDIARG_COLORFILL data);
HRESULT copySubResourceRegion(UINT dstIndex, const RECT& dstRect,
HANDLE src, UINT srcIndex, const RECT& srcRect);
void disableClamp();
void* getLockPtr(UINT subResourceIndex);
RECT getRect(UINT subResourceIndex) const;

View File

@ -15,11 +15,11 @@
#include <Shaders/CubicConvolution4.h>
#include <Shaders/DepthBlt.h>
#include <Shaders/DrawCursor.h>
#include <Shaders/Gamma.h>
#include <Shaders/Lanczos.h>
#include <Shaders/LockRef.h>
#include <Shaders/PaletteLookup.h>
#include <Shaders/Point.h>
#include <Shaders/PointNoFilter.h>
#include <Shaders/TextureSampler.h>
#define CONCAT_(a, b) a##b
@ -28,6 +28,10 @@
namespace
{
const UINT CF_HORIZONTAL = 1;
const UINT CF_GAMMARAMP = 2;
const UINT CF_DITHERING = 4;
D3DDDI_GAMMA_RAMP_RGB256x3x16 g_gammaRamp;
bool g_isGammaRampDefault = true;
bool g_isGammaRampInvalidated = false;
@ -83,11 +87,11 @@ namespace D3dDdi
}
, m_psDepthBlt(createPixelShader(g_psDepthBlt))
, m_psDrawCursor(createPixelShader(g_psDrawCursor))
, m_psGamma(createPixelShader(g_psGamma))
, m_psLanczos(createPixelShader(g_psLanczos))
, m_psLockRef(createPixelShader(g_psLockRef))
, m_psPaletteLookup(createPixelShader(g_psPaletteLookup))
, m_psPoint(createPixelShader(g_psPoint))
, m_psPointNoFilter(createPixelShader(g_psPointNoFilter))
, m_psTextureSampler(createPixelShader(g_psTextureSampler))
, m_vertexShaderDecl(createVertexShaderDecl())
, m_convolutionParams{}
@ -160,9 +164,13 @@ namespace D3dDdi
const auto& srcSurface = srcResource.getFixedDesc().pSurfList[srcSubResourceIndex];
const auto& dstSurface = dstResource.getFixedDesc().pSurfList[dstSubResourceIndex];
const bool srgb = (filter & D3DTEXF_SRGB) &&
(srcResource.getFormatOp().Operations & FORMATOP_SRGBREAD) &&
(dstResource.getFormatOp().Operations & FORMATOP_SRGBWRITE);
bool srgbRead = (filter & D3DTEXF_SRGBREAD) && (srcResource.getFormatOp().Operations & FORMATOP_SRGBREAD);
bool srgbWrite = (filter & D3DTEXF_SRGBWRITE) && (dstResource.getFormatOp().Operations & FORMATOP_SRGBWRITE);
if (D3DTEXF_SRGB == HIWORD(filter) && (!srgbRead || !srgbWrite))
{
srgbRead = false;
srgbWrite = false;
}
auto& state = m_device.getState();
state.setSpriteMode(false);
@ -189,7 +197,7 @@ namespace D3dDdi
state.setTempRenderState({ D3DDDIRS_MULTISAMPLEANTIALIAS, FALSE });
state.setTempRenderState({ D3DDDIRS_COLORWRITEENABLE, 0xF });
state.setTempRenderState({ D3DDDIRS_SCISSORTESTENABLE, FALSE });
state.setTempRenderState({ D3DDDIRS_SRGBWRITEENABLE, srgb });
state.setTempRenderState({ D3DDDIRS_SRGBWRITEENABLE, srgbWrite });
if (alpha)
{
@ -209,8 +217,7 @@ namespace D3dDdi
state.setTempRenderState({ D3DDDIRS_DESTBLEND, D3DBLEND_INVSRCALPHA });
}
setTempTextureStage(0, srcResource, srcRect, LOWORD(filter));
state.setTempTextureStageState({ 0, D3DDDITSS_SRGBTEXTURE, srgb });
setTempTextureStage(0, srcResource, srcRect, LOWORD(filter) | (srgbRead ? D3DTEXF_SRGBREAD : 0));
state.setTempStreamSourceUm({ 0, sizeof(Vertex) }, m_vertices.data());
@ -246,18 +253,18 @@ namespace D3dDdi
void ShaderBlitter::convolution(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
bool isHorizontal, Float2 support, HANDLE pixelShader,
const std::function<void(bool)> setExtraParams)
Float2 support, HANDLE pixelShader, const std::function<void(bool)> setExtraParams, DWORD flags)
{
LOG_FUNC("ShaderBlitter::convolution", static_cast<HANDLE>(dstResource), dstSubResourceIndex, dstRect,
static_cast<HANDLE>(srcResource), srcSubResourceIndex, srcRect,
isHorizontal, support, pixelShader, static_cast<bool>(setExtraParams));
support, pixelShader, static_cast<bool>(setExtraParams), flags);
const auto& srcDesc = srcResource.getFixedDesc().pSurfList[0];
const Float2 dstSize(dstRect.right - dstRect.left, dstRect.bottom - dstRect.top);
const Float2 srcSize(srcRect.right - srcRect.left, srcRect.bottom - srcRect.top);
const Float2 scale = dstSize / srcSize;
const bool isHorizontal = flags & CF_HORIZONTAL;
const bool isDual = srcSize.x != dstSize.x && srcSize.y != dstSize.y;
const Float2 compMaskPri = isHorizontal ? Float2(1, 0) : Float2(0, 1);
const Float2 compMaskSec = isHorizontal ? Float2(0, 1) : Float2(1, 0);
@ -291,14 +298,43 @@ namespace D3dDdi
setExtraParams(isHorizontal);
}
struct BoolParams
{
BOOL useSrgbRead;
BOOL useSrgbReadNeg;
BOOL useSrgbWrite;
BOOL useGammaRamp;
BOOL useDithering;
};
BoolParams boolParams = {};
boolParams.useSrgbRead = !(srcResource.getFormatOp().Operations & FORMATOP_SRGBREAD);
boolParams.useSrgbReadNeg = !boolParams.useSrgbRead;
boolParams.useSrgbWrite = (flags & (CF_GAMMARAMP | CF_DITHERING)) ||
!(dstResource.getFormatOp().Operations & FORMATOP_SRGBWRITE);
boolParams.useGammaRamp = flags & CF_GAMMARAMP;
boolParams.useDithering = flags & CF_DITHERING;
DeviceState::TempPixelShaderConstB tempPsConstB(m_device.getState(), { 0, 5 }, &boolParams.useSrgbRead);
const DeviceState::ShaderConstI reg = { dot(sampleCountHalf - 1, Int2(compMaskPri)) };
DeviceState::TempPixelShaderConstI tempPsConstI(m_device.getState(), { 0, 1 }, &reg);
DeviceState::TempPixelShaderConst tempPsConst(m_device.getState(),
{ 0, sizeof(m_convolutionParams) / sizeof(DeviceState::ShaderConstF) },
reinterpret_cast<DeviceState::ShaderConstF*>(&m_convolutionParams));
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
pixelShader, (p.support <= 1 ? D3DTEXF_LINEAR : D3DTEXF_POINT) | D3DTEXF_SRGB);
UINT filter = (p.support <= 1 && !boolParams.useSrgbRead) ? D3DTEXF_LINEAR : D3DTEXF_POINT;
if (!boolParams.useSrgbRead && 0 != support.x)
{
filter |= D3DTEXF_SRGBREAD;
}
if (!boolParams.useSrgbWrite && 0 != support.x)
{
filter |= D3DTEXF_SRGBWRITE;
}
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect, pixelShader, filter);
}
void ShaderBlitter::convolutionBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
@ -315,15 +351,84 @@ namespace D3dDdi
const Float2 kernelCoordStep = min(scale, 1.0f);
const Float2 sampleCountHalf = support / kernelCoordStep;
if (srcSize.y == dstSize.y || sampleCountHalf.y <= 1)
DWORD flags = 0;
Resource* gammaRampTexture = nullptr;
if (!g_isGammaRampDefault && nullptr != (gammaRampTexture = m_device.getRepo().getGammaRampTexture()))
{
return convolution(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
true, support, pixelShader, setExtraParams);
flags |= CF_GAMMARAMP;
}
else if (srcSize.x == dstSize.x || sampleCountHalf.x <= 1)
const auto& dstFi = getFormatInfo(m_device.getAdapter().getRenderColorDepthDstFormat());
const auto& srcFi = getFormatInfo(srcResource.getFixedDesc().Format);
BYTE maxBpcDiff = 0;
maxBpcDiff = std::max<BYTE>(maxBpcDiff, srcFi.red.bitCount - dstFi.red.bitCount);
maxBpcDiff = std::max<BYTE>(maxBpcDiff, srcFi.green.bitCount - dstFi.green.bitCount);
maxBpcDiff = std::max<BYTE>(maxBpcDiff, srcFi.blue.bitCount - dstFi.blue.bitCount);
Resource* ditherTexture = nullptr;
DWORD ditherSize = std::min(1 << maxBpcDiff, 16);
if (0 != maxBpcDiff && nullptr != (ditherTexture = m_device.getRepo().getDitherTexture(ditherSize)))
{
flags |= CF_DITHERING;
}
if ((flags & CF_GAMMARAMP) && g_isGammaRampInvalidated)
{
D3DDDIARG_LOCK lock = {};
lock.hResource = *gammaRampTexture;
lock.Flags.Discard = 1;
m_device.getOrigVtable().pfnLock(m_device, &lock);
if (lock.pSurfData)
{
auto ptr = static_cast<BYTE*>(lock.pSurfData);
setGammaValues(ptr, g_gammaRamp.Red);
setGammaValues(ptr + lock.Pitch, g_gammaRamp.Green);
setGammaValues(ptr + 2 * lock.Pitch, g_gammaRamp.Blue);
D3DDDIARG_UNLOCK unlock = {};
unlock.hResource = *gammaRampTexture;
m_device.getOrigVtable().pfnUnlock(m_device, &unlock);
g_isGammaRampInvalidated = false;
}
else
{
flags &= ~CF_GAMMARAMP;
}
}
if (flags & CF_GAMMARAMP)
{
setTempTextureStage(1, *gammaRampTexture, srcRect, D3DTEXF_LINEAR);
}
if (flags & CF_DITHERING)
{
setTempTextureStage(2, *ditherTexture, dstRect, D3DTEXF_POINT, D3DTADDRESS_WRAP);
m_convolutionParams.maxRgb[0] = static_cast<float>(1 << dstFi.red.bitCount) - 1;
m_convolutionParams.maxRgb[1] = static_cast<float>(1 << dstFi.green.bitCount) - 1;
m_convolutionParams.maxRgb[2] = static_cast<float>(1 << dstFi.blue.bitCount) - 1;
for (unsigned i = 0; i < 3; ++i)
{
m_convolutionParams.maxRgbRcp[i] = 1.0f / m_convolutionParams.maxRgb[i];
}
const float d = static_cast<float>(ditherSize * ditherSize);
m_convolutionParams.ditherScale = (d - 1) / d;
m_convolutionParams.ditherOffset = 0.5f / d;
}
if (srcSize.y == dstSize.y ||
0 == support.y ||
sampleCountHalf.y <= 1 && (srcResource.getFormatOp().Operations & FORMATOP_SRGBREAD))
{
return convolution(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
false, support, pixelShader, setExtraParams);
support, pixelShader, setExtraParams, flags | CF_HORIZONTAL);
}
if (srcSize.x == dstSize.x ||
sampleCountHalf.x <= 1 && (srcResource.getFormatOp().Operations & FORMATOP_SRGBREAD))
{
return convolution(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
support, pixelShader, setExtraParams, flags);
}
const bool isHorizontalFirst = dstSize.x * srcSize.y <= srcSize.x * dstSize.y;
@ -337,16 +442,17 @@ namespace D3dDdi
rect.bottom = dstSize.y;
}
auto rt = m_device.getRepo().getNextRenderTarget(rect.right, rect.bottom, &srcResource, &dstResource).resource;
auto rt = m_device.getRepo().getNextRenderTarget(rect.right, rect.bottom,
srcResource.getFixedDesc().Format, &srcResource, &dstResource).resource;
if (!rt)
{
return;
}
convolution(*rt, 0, rect, srcResource, srcSubResourceIndex, srcRect,
isHorizontalFirst, support, pixelShader, setExtraParams);
support, pixelShader, setExtraParams, isHorizontalFirst ? CF_HORIZONTAL : 0);
convolution(dstResource, dstSubResourceIndex, dstRect, *rt, 0, rect,
!isHorizontalFirst, support, pixelShader, setExtraParams);
support, pixelShader, setExtraParams, flags | (isHorizontalFirst ? 0 : CF_HORIZONTAL));
}
std::unique_ptr<void, ResourceDeleter> ShaderBlitter::createPixelShader(const BYTE* code, UINT size)
@ -427,14 +533,7 @@ namespace D3dDdi
if (cur.maskTexture)
{
D3DDDIARG_BLT data = {};
data.hSrcResource = dstResource;
data.SrcSubResourceIndex = dstSubResourceIndex;
data.SrcRect = clippedDstRect;
data.hDstResource = *cur.tempTexture;
data.DstRect = clippedSrcRect;
m_device.getOrigVtable().pfnBlt(m_device, &data);
cur.tempTexture->copySubResourceRegion(0, clippedSrcRect, dstResource, dstSubResourceIndex, clippedDstRect);
setTempTextureStage(1, *cur.maskTexture, clippedSrcRect, D3DTEXF_POINT);
setTempTextureStage(2, *cur.colorTexture, clippedSrcRect, D3DTEXF_POINT);
setTempTextureStage(3, *xorTexture, clippedSrcRect, D3DTEXF_POINT);
@ -493,75 +592,42 @@ namespace D3dDdi
m_device.flushPrimitives();
}
void ShaderBlitter::displayBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
void ShaderBlitter::displayBlt(Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect)
{
auto& repo = m_device.getRepo();
const bool useGamma = !g_isGammaRampDefault && repo.getGammaRampTexture();
auto filter = Config::displayFilter.get();
if (Rect::isEqualSize(dstRect, srcRect))
{
if (useGamma)
{
gammaBlt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect);
return;
}
D3DDDIARG_BLT data = {};
data.hSrcResource = srcResource;
data.SrcSubResourceIndex = srcSubResourceIndex;
data.SrcRect = srcRect;
data.hDstResource = dstResource;
data.DstSubResourceIndex = dstSubResourceIndex;
data.DstRect = dstRect;
data.Flags.Point = 1;
m_device.getOrigVtable().pfnBlt(m_device, &data);
return;
filter = Config::Settings::DisplayFilter::POINT;
}
RECT r = { 0, 0, dstRect.right - dstRect.left, dstRect.bottom - dstRect.top };
Resource* rtGamma = nullptr;
if (useGamma)
{
rtGamma = repo.getNextRenderTarget(r.right, r.bottom, &srcResource).resource;
}
const auto& rt = rtGamma ? *rtGamma : dstResource;
const auto rtIndex = rtGamma ? 0 : dstSubResourceIndex;
const auto& rtRect = rtGamma ? r : dstRect;
switch (Config::displayFilter.get())
switch (filter)
{
case Config::Settings::DisplayFilter::POINT:
m_device.getShaderBlitter().pointBlt(rt, rtIndex, rtRect,
m_device.getShaderBlitter().pointBlt(dstResource, dstSubResourceIndex, dstRect,
srcResource, srcSubResourceIndex, srcRect);
break;
case Config::Settings::DisplayFilter::BILINEAR:
m_device.getShaderBlitter().bilinearBlt(rt, rtIndex, rtRect,
m_device.getShaderBlitter().bilinearBlt(dstResource, dstSubResourceIndex, dstRect,
srcResource, srcSubResourceIndex, srcRect, Config::displayFilter.getParam());
break;
case Config::Settings::DisplayFilter::BICUBIC:
m_device.getShaderBlitter().bicubicBlt(rt, rtIndex, rtRect,
m_device.getShaderBlitter().bicubicBlt(dstResource, dstSubResourceIndex, dstRect,
srcResource, srcSubResourceIndex, srcRect, Config::displayFilter.getParam());
break;
case Config::Settings::DisplayFilter::LANCZOS:
m_device.getShaderBlitter().lanczosBlt(rt, rtIndex, rtRect,
m_device.getShaderBlitter().lanczosBlt(dstResource, dstSubResourceIndex, dstRect,
srcResource, srcSubResourceIndex, srcRect, Config::displayFilter.getParam());
break;
case Config::Settings::DisplayFilter::SPLINE:
m_device.getShaderBlitter().splineBlt(rt, rtIndex, rtRect,
m_device.getShaderBlitter().splineBlt(dstResource, dstSubResourceIndex, dstRect,
srcResource, srcSubResourceIndex, srcRect, Config::displayFilter.getParam());
break;
}
if (rtGamma)
{
gammaBlt(dstResource, dstSubResourceIndex, dstRect, rt, rtIndex, rtRect);
}
}
void ShaderBlitter::drawRect(const RECT& srcRect, const RectF& dstRect, UINT srcWidth, UINT srcHeight)
@ -580,44 +646,6 @@ namespace D3dDdi
m_device.pfnDrawPrimitive(&dp, nullptr);
}
void ShaderBlitter::gammaBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect)
{
LOG_FUNC("ShaderBlitter::gammaBlt", static_cast<HANDLE>(dstResource), dstSubResourceIndex, dstRect,
static_cast<HANDLE>(srcResource), srcSubResourceIndex, srcRect);
auto gammaRampTexture(m_device.getRepo().getGammaRampTexture());
if (!gammaRampTexture)
{
return;
}
if (g_isGammaRampInvalidated)
{
D3DDDIARG_LOCK lock = {};
lock.hResource = *gammaRampTexture;
lock.Flags.Discard = 1;
m_device.getOrigVtable().pfnLock(m_device, &lock);
if (!lock.pSurfData)
{
return;
}
auto ptr = static_cast<BYTE*>(lock.pSurfData);
setGammaValues(ptr, g_gammaRamp.Red);
setGammaValues(ptr + lock.Pitch, g_gammaRamp.Green);
setGammaValues(ptr + 2 * lock.Pitch, g_gammaRamp.Blue);
D3DDDIARG_UNLOCK unlock = {};
unlock.hResource = *gammaRampTexture;
m_device.getOrigVtable().pfnUnlock(m_device, &unlock);
g_isGammaRampInvalidated = false;
}
setTempTextureStage(1, *gammaRampTexture, srcRect, D3DTEXF_POINT);
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, 0, srcRect, m_psGamma.get(), D3DTEXF_POINT);
}
void ShaderBlitter::lanczosBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, UINT lobes)
{
@ -680,8 +708,18 @@ namespace D3dDdi
LOG_FUNC("ShaderBlitter::pointBlt", static_cast<HANDLE>(dstResource), dstSubResourceIndex, dstRect,
static_cast<HANDLE>(srcResource), srcSubResourceIndex, srcRect);
convolutionBlt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
0.5f, m_psPoint.get());
auto dstSize = Rect::getSize(dstRect);
auto srcSize = Rect::getSize(srcRect);
if (dstSize.cx >= srcSize.cx && dstSize.cy >= srcSize.cy)
{
convolutionBlt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
0.0f, m_psPointNoFilter.get());
}
else
{
convolutionBlt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
0.5f, m_psPoint.get());
}
}
void ShaderBlitter::resetGammaRamp()
@ -701,16 +739,18 @@ namespace D3dDdi
g_isGammaRampInvalidated = !g_isGammaRampDefault;
}
void ShaderBlitter::setTempTextureStage(UINT stage, const Resource& texture, const RECT& rect, UINT filter)
void ShaderBlitter::setTempTextureStage(UINT stage, const Resource& texture, const RECT& rect, UINT filter,
UINT textureAddress)
{
auto& state = m_device.getState();
state.setTempTexture(stage, texture);
state.setTempTextureStageState({ stage, D3DDDITSS_TEXCOORDINDEX, stage });
state.setTempTextureStageState({ stage, D3DDDITSS_ADDRESSU, D3DTADDRESS_CLAMP });
state.setTempTextureStageState({ stage, D3DDDITSS_ADDRESSV, D3DTADDRESS_CLAMP });
state.setTempTextureStageState({ stage, D3DDDITSS_MAGFILTER, filter });
state.setTempTextureStageState({ stage, D3DDDITSS_MINFILTER, filter });
state.setTempTextureStageState({ stage, D3DDDITSS_ADDRESSU, textureAddress });
state.setTempTextureStageState({ stage, D3DDDITSS_ADDRESSV, textureAddress });
state.setTempTextureStageState({ stage, D3DDDITSS_MAGFILTER, LOWORD(filter) });
state.setTempTextureStageState({ stage, D3DDDITSS_MINFILTER, LOWORD(filter) });
state.setTempTextureStageState({ stage, D3DDDITSS_MIPFILTER, D3DTEXF_NONE });
state.setTempTextureStageState({ stage, D3DDDITSS_SRGBTEXTURE, 0 != (filter & D3DTEXF_SRGBREAD) });
state.setTempRenderState({ static_cast<D3DDDIRENDERSTATETYPE>(D3DDDIRS_WRAP0 + stage), 0 });
auto& si = texture.getFixedDesc().pSurfList[0];

View File

@ -41,9 +41,7 @@ namespace D3dDdi
HCURSOR cursor, POINT pt);
void depthBlt(const Resource& dstResource, const RECT& dstRect,
const Resource& srcResource, const RECT& srcRect, HANDLE nullResource);
void displayBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect);
void gammaBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
void displayBlt(Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect);
void lanczosBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, UINT lobes);
@ -80,6 +78,11 @@ namespace D3dDdi
Float2 kernelCoordStepPri;
float support;
float supportRcp;
DeviceState::ShaderConstF maxRgb;
DeviceState::ShaderConstF maxRgbRcp;
float ditherScale;
float ditherOffset;
Float2 padding;
alignas(sizeof(DeviceState::ShaderConstF)) std::array<DeviceState::ShaderConstF, 4> extra;
};
@ -96,8 +99,7 @@ namespace D3dDdi
UINT filter, UINT flags = 0, const BYTE* alpha = nullptr, const Gdi::Region& srcRgn = nullptr);
void convolution(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
bool isHorizontal, Float2 support, HANDLE pixelShader,
const std::function<void(bool)> setExtraParams);
Float2 support, HANDLE pixelShader, const std::function<void(bool)> setExtraParams, DWORD flags);
void convolutionBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
Float2 support, HANDLE pixelShader, const std::function<void(bool)> setExtraParams = {});
@ -111,7 +113,8 @@ namespace D3dDdi
std::unique_ptr<void, ResourceDeleter> createPixelShader(const BYTE* code, UINT size);
std::unique_ptr<void, ResourceDeleter> createVertexShaderDecl();
void drawRect(const RECT& srcRect, const RectF& dstRect, UINT srcWidth, UINT srcHeight);
void setTempTextureStage(UINT stage, const Resource& texture, const RECT& rect, UINT filter);
void setTempTextureStage(UINT stage, const Resource& texture, const RECT& rect, UINT filter,
UINT textureAddress = D3DTADDRESS_CLAMP);
void setTextureCoords(UINT stage, const RECT& rect, UINT width, UINT height);
Device& m_device;
@ -120,12 +123,13 @@ namespace D3dDdi
std::unique_ptr<void, ResourceDeleter> m_psColorKeyBlend;
std::unique_ptr<void, ResourceDeleter> m_psCubicConvolution[3];
std::unique_ptr<void, ResourceDeleter> m_psDepthBlt;
std::unique_ptr<void, ResourceDeleter> m_psDitheredGammaControl;
std::unique_ptr<void, ResourceDeleter> m_psDrawCursor;
std::unique_ptr<void, ResourceDeleter> m_psGamma;
std::unique_ptr<void, ResourceDeleter> m_psLanczos;
std::unique_ptr<void, ResourceDeleter> m_psLockRef;
std::unique_ptr<void, ResourceDeleter> m_psPaletteLookup;
std::unique_ptr<void, ResourceDeleter> m_psPoint;
std::unique_ptr<void, ResourceDeleter> m_psPointNoFilter;
std::unique_ptr<void, ResourceDeleter> m_psTextureSampler;
std::unique_ptr<void, ResourceDeleter> m_vertexShaderDecl;
ConvolutionParams m_convolutionParams;

View File

@ -18,6 +18,27 @@ namespace
{
std::map<LUID, D3dDdi::SurfaceRepository> g_repositories;
bool g_enableSurfaceCheck = true;
void initDitherTexture(BYTE* tex, DWORD pitch, DWORD x, DWORD y, DWORD size, DWORD mul, DWORD value)
{
if (1 == size)
{
tex[y * pitch + x] = static_cast<BYTE>(value);
}
else
{
size /= 2;
initDitherTexture(tex, pitch, x, y, size, 4 * mul, value + 0 * mul);
initDitherTexture(tex, pitch, x + size, y, size, 4 * mul, value + 2 * mul);
initDitherTexture(tex, pitch, x, y + size, size, 4 * mul, value + 3 * mul);
initDitherTexture(tex, pitch, x + size, y + size, size, 4 * mul, value + 1 * mul);
}
}
void initDitherTexture(BYTE* tex, DWORD pitch, DWORD size)
{
initDitherTexture(tex, pitch, 0, 0, size, 1, 0);
}
}
namespace D3dDdi
@ -201,6 +222,14 @@ namespace D3dDdi
return true;
}
Resource* SurfaceRepository::getDitherTexture(DWORD size)
{
return getInitializedResource(m_ditherTexture, size, size, D3DDDIFMT_L8, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
[](const DDSURFACEDESC2& desc) {
initDitherTexture(static_cast<BYTE*>(desc.lpSurface), desc.lPitch, 16);
});
}
Resource* SurfaceRepository::getGammaRampTexture()
{
return getSurface(m_gammaRampTexture, 256, 3, D3DDDIFMT_L8, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY).resource;
@ -245,19 +274,21 @@ namespace D3dDdi
}
const SurfaceRepository::Surface& SurfaceRepository::getNextRenderTarget(
DWORD width, DWORD height, const Resource* currentSrcRt, const Resource* currentDstRt)
DWORD width, DWORD height, D3DDDIFORMAT format, const Resource* currentSrcRt, const Resource* currentDstRt)
{
const bool hq = getFormatInfo(format).red.bitCount > 8;
auto& renderTargets = hq ? m_hqRenderTargets : m_renderTargets;
std::size_t index = 0;
while (index < m_renderTargets.size())
while (index < renderTargets.size())
{
auto rt = m_renderTargets[index].resource;
auto rt = renderTargets[index].resource;
if (!rt || rt != currentSrcRt && rt != currentDstRt)
{
break;
}
++index;
}
return getTempSurface(m_renderTargets[index], width, height, D3DDDIFMT_X8R8G8B8,
return getTempSurface(renderTargets[index], width, height, hq ? format : D3DDDIFMT_X8R8G8B8,
DDSCAPS_3DDEVICE | DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY);
}

View File

@ -40,10 +40,11 @@ namespace D3dDdi
SurfaceRepository();
Cursor getCursor(HCURSOR cursor);
Resource* getDitherTexture(DWORD size);
Resource* getLogicalXorTexture();
Resource* getPaletteTexture();
Resource* getGammaRampTexture();
const Surface& getNextRenderTarget(DWORD width, DWORD height,
const Surface& getNextRenderTarget(DWORD width, DWORD height, D3DDDIFORMAT format,
const Resource* currentSrcRt = nullptr, const Resource* currentDstRt = nullptr);
Surface& getSurface(Surface& surface, DWORD width, DWORD height,
D3DDDIFORMAT format, DWORD caps, UINT surfaceCount = 1, DWORD caps2 = 0);
@ -74,10 +75,12 @@ namespace D3dDdi
Surface m_cursorMaskTexture;
Surface m_cursorColorTexture;
Surface m_cursorTempTexture;
Surface m_ditherTexture;
Surface m_gammaRampTexture;
Surface m_logicalXorTexture;
Surface m_paletteTexture;
std::array<Surface, 3> m_renderTargets;
std::array<Surface, 3> m_hqRenderTargets;
std::map<D3DDDIFORMAT, Surface> m_textures;
std::vector<Surface> m_releasedSurfaces;
Surface m_sysMemSurface;

View File

@ -486,11 +486,11 @@
<FxCompile Include="Shaders\CubicConvolution4.hlsl" />
<FxCompile Include="Shaders\DepthBlt.hlsl" />
<FxCompile Include="Shaders\DrawCursor.hlsl" />
<FxCompile Include="Shaders\Gamma.hlsl" />
<FxCompile Include="Shaders\Lanczos.hlsl" />
<FxCompile Include="Shaders\LockRef.hlsl" />
<FxCompile Include="Shaders\PaletteLookup.hlsl" />
<FxCompile Include="Shaders\Point.hlsl" />
<FxCompile Include="Shaders\PointNoFilter.hlsl" />
<FxCompile Include="Shaders\TextureSampler.hlsl" />
<FxCompile Include="Shaders\VertexFixup.hlsl">
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Vertex</ShaderType>

View File

@ -1136,9 +1136,6 @@
<FxCompile Include="Shaders\VertexFixup.hlsl">
<Filter>Shaders</Filter>
</FxCompile>
<FxCompile Include="Shaders\Gamma.hlsl">
<Filter>Shaders</Filter>
</FxCompile>
<FxCompile Include="Shaders\LockRef.hlsl">
<Filter>Shaders</Filter>
</FxCompile>
@ -1169,6 +1166,9 @@
<FxCompile Include="Shaders\Point.hlsl">
<Filter>Shaders</Filter>
</FxCompile>
<FxCompile Include="Shaders\PointNoFilter.hlsl">
<Filter>Shaders</Filter>
</FxCompile>
</ItemGroup>
<ItemGroup>
<Image Include="arrow.bmp">

View File

@ -1,8 +1,16 @@
sampler2D s_texture : register(s0);
sampler2D s_gammaRamp : register(s1);
sampler2D s_dither : register(s2);
int g_sampleCountHalfMinusOne : register(i0);
float4 c[32] : register(c0);
float4 g_extraParams[4] : register(c6);
float4 g_extraParams[4] : register(c9);
bool g_useSrgbRead : register(b0);
bool g_useSrgbReadNeg : register(b1);
bool g_useSrgbWrite : register(b2);
bool g_useGammaRamp : register(b3);
bool g_useDithering : register(b4);
static const float2 g_textureSize = c[0].xy;
static const float2 g_sampleCoordOffset = c[0].zw;
@ -15,6 +23,10 @@ static const float2 g_textureCoordStepSec = c[4].zw;
static const float2 g_kernelCoordStepPri = c[5].xy;
static const float g_support = c[5].z;
static const float g_supportRcp = c[5].w;
static const float4 g_maxRgb = c[6];
static const float4 g_maxRgbRcp = c[7];
static const float g_ditherScale = c[8].x;
static const float g_ditherOffset = c[8].y;
#ifdef NONNEGATIVE
float4 kernel(float4 x);
@ -22,14 +34,35 @@ float4 kernel(float4 x);
float kernel(float x);
#endif
void addSamples(inout float4 colorSum, float4 textureCoord, float4 weights)
float4 srgb2lin(float4 color)
{
return float4(color.rgb < 0.04045f ? color.rgb / 12.92f : pow((abs(color.rgb) + 0.055f) / 1.055f, 2.4f), 1);
}
void addSamples(inout float4 color, float4 textureCoord, float4 weights)
{
#ifdef NONNEGATIVE
const float weightSum = weights.x + weights.z;
colorSum += weightSum * tex2Dlod(s_texture, lerp(textureCoord.xyxy, textureCoord.zwzw, weights.z / weightSum));
#else
colorSum += weights.x * tex2Dlod(s_texture, textureCoord.xyxy);
colorSum += weights.z * tex2Dlod(s_texture, textureCoord.zwzw);
[branch]
if (g_useSrgbRead)
{
#endif
float4 color1 = tex2Dlod(s_texture, textureCoord.xyxy);
float4 color2 = tex2Dlod(s_texture, textureCoord.zwzw);
[branch]
if (g_useSrgbRead)
{
color1 = srgb2lin(color1);
color2 = srgb2lin(color2);
}
color += weights.x * color1;
color += weights.z * color2;
#ifdef NONNEGATIVE
}
else
{
const float weightSum = weights.x + weights.z;
color += weightSum * tex2Dlod(s_texture, lerp(textureCoord.xyxy, textureCoord.zwzw, weights.z / weightSum));
}
#endif
}
@ -42,8 +75,16 @@ float4 getWeights(float4 kernelCoord)
#endif
}
float4 main(float2 texCoord : TEXCOORD0) : COLOR0
float4 normalize(float4 color)
{
return color * 255.0f / 256.0f + 0.5f / 256.0f;
}
float4 main(float2 texCoord : TEXCOORD0, float2 ditherCoord : TEXCOORD2) : COLOR0
{
#ifdef NOFILTER
float4 color = float4(tex2D(s_texture, texCoord).rgb, 1);
#else
const float2 sampleCoord = mad(texCoord, g_textureSize, g_sampleCoordOffset);
const float2 sampleCoordFrac = frac(sampleCoord);
const float2 sampleCoordInt = sampleCoord - sampleCoordFrac;
@ -55,21 +96,54 @@ float4 main(float2 texCoord : TEXCOORD0) : COLOR0
const float4 weights = getWeights(kernelCoord);
#ifdef NONNEGATIVE
[branch] if (g_sampleCoordOffset.x == g_sampleCoordOffset.y)
[branch]
if (g_useSrgbReadNeg)
{
textureCoord = lerp(textureCoord, textureCoord + g_textureCoordStepSec.xyxy, weights.w / (weights.y + weights.w));
[branch]
if (g_sampleCoordOffset.x == g_sampleCoordOffset.y)
{
textureCoord = lerp(textureCoord, textureCoord + g_textureCoordStepSec.xyxy, weights.w / (weights.y + weights.w));
}
}
#endif
#endif // NONNEGATIVE
float4 colorSum = 0;
addSamples(colorSum, textureCoord, weights);
float4 color = 0;
addSamples(color, textureCoord, weights);
for (int i = 0; i < g_sampleCountHalfMinusOne; ++i)
{
textureCoord += g_textureCoordStepPri.xyxy;
kernelCoord += g_kernelCoordStepPri.xyxy;
addSamples(colorSum, textureCoord, getWeights(kernelCoord));
addSamples(color, textureCoord, getWeights(kernelCoord));
}
return colorSum / colorSum.a;
color /= color.a;
[branch]
if (g_useSrgbWrite)
{
color = saturate(color);
color.rgb = color.rgb < 0.0031308f ? 12.92f * color.rgb : 1.055f * pow(color.rgb, 1.0f / 2.4f) - 0.055f;
#endif // NOFILTER
[branch]
if (g_useGammaRamp)
{
color = normalize(color);
color.r = tex2Dlod(s_gammaRamp, float4(color.r, 0.0f, 0, 0)).r;
color.g = tex2Dlod(s_gammaRamp, float4(color.g, 0.5f, 0, 0)).r;
color.b = tex2Dlod(s_gammaRamp, float4(color.b, 1.0f, 0, 0)).r;
}
[branch]
if (g_useDithering)
{
const float dither = tex2D(s_dither, ditherCoord).r * g_ditherScale + g_ditherOffset;
color = floor(color * g_maxRgb + dither) * g_maxRgbRcp;
}
#ifndef NOFILTER
}
#endif
return color;
}

View File

@ -1,12 +0,0 @@
sampler2D s_texture : register(s0);
sampler2D s_gammaRamp : register(s1);
float4 main(float2 texCoord : TEXCOORD0) : COLOR0
{
const float4 color = tex2D(s_texture, texCoord);
return float4(
tex2D(s_gammaRamp, float2(color.r, 0.0f)).r,
tex2D(s_gammaRamp, float2(color.g, 0.5f)).r,
tex2D(s_gammaRamp, float2(color.b, 1.0f)).r,
0);
}

View File

@ -0,0 +1,2 @@
#define NOFILTER
#include "Convolution.hlsli"