Skip to content

Commit

Permalink
Add "SDR Display nits" setting for tonemapping HDR to SDR.
Browse files Browse the repository at this point in the history
  • Loading branch information
clsid2 committed May 14, 2024
1 parent e8b0e4d commit 524a7d0
Show file tree
Hide file tree
Showing 15 changed files with 98 additions and 38 deletions.
10 changes: 6 additions & 4 deletions Shaders/d3d11/ps_convert_pq_to_sdr.hlsl
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
Texture2D tex : register(t0);
SamplerState samp : register(s0);

cbuffer PS_COLOR_TRANSFORM : register(b0)
{
float LuminanceScale;
};

#include "../convert/conv_matrix.hlsl"
#include "../convert/st2084.hlsl"
#include "../convert/hdr_tone_mapping.hlsl"
#include "../convert/colorspace_gamut_conversion.hlsl"

#define SRC_LUMINANCE_PEAK 10000.0
#define DISPLAY_LUMINANCE_PEAK 125.0

struct PS_INPUT
{
float4 Pos : SV_POSITION;
Expand All @@ -21,7 +23,7 @@ float4 main(PS_INPUT input) : SV_Target

// PQ to Linear
color = saturate(color);
color = ST2084ToLinear(color, SRC_LUMINANCE_PEAK/DISPLAY_LUMINANCE_PEAK);
color = ST2084ToLinear(color, LuminanceScale);

color.rgb = ToneMappingHable(color.rgb);
color.rgb = Colorspace_Gamut_Conversion_2020_to_709(color.rgb);
Expand Down
10 changes: 6 additions & 4 deletions Shaders/d3d11/ps_fixconvert_pq_to_sdr.hlsl
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
Texture2D tex : register(t0);
SamplerState samp : register(s0);

cbuffer PS_COLOR_TRANSFORM : register(b0)
{
float LuminanceScale;
};

#include "../convert/conv_matrix.hlsl"
#include "../convert/st2084.hlsl"
#include "../convert/hdr_tone_mapping.hlsl"
#include "../convert/colorspace_gamut_conversion.hlsl"

static const float4x4 fix_bt2020_matrix = mul(ycbcr2020nc_rgb, rgb_ycbcr709);

#define SRC_LUMINANCE_PEAK 10000.0
#define DISPLAY_LUMINANCE_PEAK 125.0

struct PS_INPUT
{
float4 Pos : SV_POSITION;
Expand All @@ -26,7 +28,7 @@ float4 main(PS_INPUT input) : SV_Target

// PQ to Linear
color = saturate(color);
color = ST2084ToLinear(color, SRC_LUMINANCE_PEAK/DISPLAY_LUMINANCE_PEAK);
color = ST2084ToLinear(color, LuminanceScale);

color.rgb = ToneMappingHable(color.rgb);
color.rgb = Colorspace_Gamut_Conversion_2020_to_709(color.rgb);
Expand Down
6 changes: 2 additions & 4 deletions Shaders/d3d9/fixconvert_hlg_to_sdr.hlsl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
sampler s0 : register(s0);
float LuminanceScale : register(c0);

#include "../convert/conv_matrix.hlsl"
#include "../convert/hlg.hlsl"
Expand All @@ -8,9 +9,6 @@ sampler s0 : register(s0);

static const float4x4 fix_bt2020_matrix = mul(ycbcr2020nc_rgb, rgb_ycbcr709);

#define SRC_LUMINANCE_PEAK 10000.0
#define DISPLAY_LUMINANCE_PEAK 125.0

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float4 color = tex2D(s0, tex); // original pixel
Expand All @@ -25,7 +23,7 @@ float4 main(float2 tex : TEXCOORD0) : COLOR

// PQ to Linear
color = saturate(color);
color = ST2084ToLinear(color, SRC_LUMINANCE_PEAK/DISPLAY_LUMINANCE_PEAK);
color = ST2084ToLinear(color, LuminanceScale);

color.rgb = ToneMappingHable(color.rgb);
color.rgb = Colorspace_Gamut_Conversion_2020_to_709(color.rgb);
Expand Down
6 changes: 2 additions & 4 deletions Shaders/d3d9/fixconvert_pq_to_sdr.hlsl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
sampler s0 : register(s0);
float LuminanceScale : register(c0);

#include "../convert/conv_matrix.hlsl"
#include "../convert/st2084.hlsl"
Expand All @@ -7,9 +8,6 @@ sampler s0 : register(s0);

static const float4x4 fix_bt2020_matrix = mul(ycbcr2020nc_rgb, rgb_ycbcr709);

#define SRC_LUMINANCE_PEAK 10000.0
#define DISPLAY_LUMINANCE_PEAK 125.0

float4 main(float2 tex : TEXCOORD0) : COLOR
{
float4 color = tex2D(s0, tex); // original pixel
Expand All @@ -19,7 +17,7 @@ float4 main(float2 tex : TEXCOORD0) : COLOR

// PQ to Linear
color = saturate(color);
color = ST2084ToLinear(color, SRC_LUMINANCE_PEAK/DISPLAY_LUMINANCE_PEAK);
color = ST2084ToLinear(color, LuminanceScale);

color.rgb = ToneMappingHable(color.rgb);
color.rgb = Colorspace_Gamut_Conversion_2020_to_709(color.rgb);
Expand Down
20 changes: 16 additions & 4 deletions Source/DX11VideoProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -398,8 +398,8 @@ CDX11VideoProcessor::CDX11VideoProcessor(CMpcVideoRenderer* pFilter, const Setti
m_iHdrToggleDisplay = config.iHdrToggleDisplay;
m_iHdrOsdBrightness = config.iHdrOsdBrightness;
m_bConvertToSdr = config.bConvertToSdr;
m_iSDRDisplayNits = config.iSDRDisplayNits;
m_bVPRTXVideoHDR = config.bVPRTXVideoHDR;

m_iVPSuperRes = config.iVPSuperRes;

m_nCurrentAdapter = -1;
Expand Down Expand Up @@ -697,6 +697,7 @@ void CDX11VideoProcessor::ReleaseDevice()
m_strShaderY = nullptr;
m_pPSFinalPass.Release();

m_pCorrectionConstants.Release();
m_pPostScaleConstants.Release();

#if TEST_SHADER
Expand Down Expand Up @@ -1700,13 +1701,19 @@ BOOL CDX11VideoProcessor::InitMediaType(const CMediaType* pmt)
hr = InitializeD3D11VP(FmtParams, origW, origH);
if (SUCCEEDED(hr)) {
UINT resId = 0;
m_pCorrectionConstants.Release();
bool bTransFunc22 = m_srcExFmt.VideoTransferFunction == DXVA2_VideoTransFunc_22
|| m_srcExFmt.VideoTransferFunction == DXVA2_VideoTransFunc_709
|| m_srcExFmt.VideoTransferFunction == DXVA2_VideoTransFunc_240M;

if (m_srcExFmt.VideoTransferFunction == MFVideoTransFunc_2084 && !(m_bHdrPassthroughSupport && m_bHdrPassthrough) && m_bConvertToSdr) {
resId = m_D3D11VP.IsPqSupported() ? IDF_PS_11_CONVERT_PQ_TO_SDR : IDF_PS_11_FIXCONVERT_PQ_TO_SDR;
m_strCorrection = L"PQ to SDR";

D3D11_BUFFER_DESC BufferDesc = { sizeof(FLOAT) * 4, D3D11_USAGE_DEFAULT, D3D11_BIND_CONSTANT_BUFFER, 0, 0, 0 };
FLOAT CorrectionConstantsData[4] = { 10000.0f / m_iSDRDisplayNits, 0, 0, 0 };
D3D11_SUBRESOURCE_DATA InitData = { &CorrectionConstantsData, 0, 0 };
EXECUTE_ASSERT(S_OK == m_pDevice->CreateBuffer(&BufferDesc, &InitData, &m_pCorrectionConstants));
}
else if (m_srcExFmt.VideoTransferFunction == MFVideoTransFunc_HLG) {
if (m_bHdrPassthroughSupport && m_bHdrPassthrough) {
Expand Down Expand Up @@ -2554,7 +2561,7 @@ HRESULT CDX11VideoProcessor::UpdateConvertColorShader()
m_srcWidth,
m_TexSrcVideo.desc.Width, m_TexSrcVideo.desc.Height,
m_srcRect, m_srcParams, m_srcExFmt, pDOVIMetadata,
m_iChromaScaling, convertType, false,
m_iChromaScaling, convertType, false, 10000.0f / m_iSDRDisplayNits,
&pShaderCode);
if (S_OK == hr) {
hr = m_pDevice->CreatePixelShader(pShaderCode->GetBufferPointer(), pShaderCode->GetBufferSize(), nullptr, &m_pPSConvertColor);
Expand All @@ -2566,7 +2573,7 @@ HRESULT CDX11VideoProcessor::UpdateConvertColorShader()
m_srcWidth,
m_TexSrcVideo.desc.Width, m_TexSrcVideo.desc.Height,
m_srcRect, m_srcParams, m_srcExFmt, pDOVIMetadata,
m_iChromaScaling, convertType, true,
m_iChromaScaling, convertType, true, 10000.0f / m_iSDRDisplayNits,
&pShaderCode);
if (S_OK == hr) {
hr = m_pDevice->CreatePixelShader(pShaderCode->GetBufferPointer(), pShaderCode->GetBufferSize(), nullptr, &m_pPSConvertColorDeint);
Expand Down Expand Up @@ -2923,7 +2930,7 @@ HRESULT CDX11VideoProcessor::Process(ID3D11Texture2D* pRenderTarget, const CRect

if (m_pPSCorrection) {
StepSetting();
hr = TextureCopyRect(*pInputTexture, pRT, rect, rect, m_pPSCorrection, nullptr, 0, false);
hr = TextureCopyRect(*pInputTexture, pRT, rect, rect, m_pPSCorrection, m_pCorrectionConstants, 0, false);
}

if (m_pPostScaleShaders.size()) {
Expand Down Expand Up @@ -3422,6 +3429,11 @@ void CDX11VideoProcessor::Configure(const Settings_t& config)
changeRTXVideoHDR = true;
}

if (config.iSDRDisplayNits != m_iSDRDisplayNits) {
m_iSDRDisplayNits = config.iSDRDisplayNits;
changeConvertShader = true;
}

if (!m_pFilter->GetActive()) {
return;
}
Expand Down
2 changes: 2 additions & 0 deletions Source/DX11VideoProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ class CDX11VideoProcessor

// D3D11 Video Processor
CD3D11VP m_D3D11VP;

CComPtr<ID3D11Buffer> m_pCorrectionConstants;
CComPtr<ID3D11PixelShader> m_pPSCorrection;
const wchar_t* m_strCorrection = nullptr;

Expand Down
14 changes: 12 additions & 2 deletions Source/DX9VideoProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ CDX9VideoProcessor::CDX9VideoProcessor(CMpcVideoRenderer* pFilter, const Setting
m_bHdrPassthrough = false;
m_iHdrToggleDisplay = false;
m_bConvertToSdr = config.bConvertToSdr;
m_iSDRDisplayNits = config.iSDRDisplayNits;

m_nCurrentAdapter = D3DADAPTER_DEFAULT;

Expand Down Expand Up @@ -1995,6 +1996,11 @@ void CDX9VideoProcessor::Configure(const Settings_t& config)
}
}

if (config.iSDRDisplayNits != m_iSDRDisplayNits) {
m_iSDRDisplayNits = config.iSDRDisplayNits;
changeConvertShader = true;
}

if (!m_pFilter->GetActive()) {
return;
}
Expand Down Expand Up @@ -2236,7 +2242,7 @@ HRESULT CDX9VideoProcessor::UpdateConvertColorShader()
m_srcWidth,
m_TexSrcVideo.Width, m_TexSrcVideo.Height,
m_srcRect, m_srcParams, m_srcExFmt, pDOVIMetadata,
m_iChromaScaling, convertType, false,
m_iChromaScaling, convertType, false, 10000.0f / m_iSDRDisplayNits,
&pShaderCode);
if (S_OK == hr) {
hr = m_pD3DDevEx->CreatePixelShader((const DWORD*)pShaderCode->GetBufferPointer(), &m_pPSConvertColor);
Expand All @@ -2248,7 +2254,7 @@ HRESULT CDX9VideoProcessor::UpdateConvertColorShader()
m_srcWidth,
m_TexSrcVideo.Width, m_TexSrcVideo.Height,
m_srcRect, m_srcParams, m_srcExFmt, pDOVIMetadata,
m_iChromaScaling, convertType, true,
m_iChromaScaling, convertType, true, 10000.0f / m_iSDRDisplayNits,
&pShaderCode);
if (S_OK == hr) {
hr = m_pD3DDevEx->CreatePixelShader((const DWORD*)pShaderCode->GetBufferPointer(), &m_pPSConvertColorDeint);
Expand Down Expand Up @@ -2660,6 +2666,10 @@ HRESULT CDX9VideoProcessor::Process(IDirect3DSurface9* pRenderTarget, const CRec

if (m_pPSCorrection) {
StepSetting();
float fConstDataHDR[][4] = {
{10000.0f / m_iSDRDisplayNits, 0.0f, 0.0f, 0.0f}
};
hr = m_pD3DDevEx->SetPixelShaderConstantF(0, (float*)fConstDataHDR, sizeof(fConstDataHDR) / sizeof(float[4]));
hr = m_pD3DDevEx->SetPixelShader(m_pPSCorrection);
hr = m_pD3DDevEx->SetRenderTarget(0, pRT);
hr = TextureCopyRect(pInputTexture, rect, rect, D3DTEXF_POINT, 0, false);
Expand Down
2 changes: 2 additions & 0 deletions Source/IVideoRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ struct Settings_t {
int iHdrToggleDisplay;
int iHdrOsdBrightness;
bool bConvertToSdr;
int iSDRDisplayNits;

Settings_t() {
SetDefault();
Expand Down Expand Up @@ -153,6 +154,7 @@ struct Settings_t {
}
bConvertToSdr = true;
iHdrOsdBrightness = 0;
iSDRDisplayNits = 125;
}
};

Expand Down
15 changes: 9 additions & 6 deletions Source/MpcVideoRenderer.rc
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ BEGIN
CONTROL "Use dithering",IDC_CHECK10,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,206,59,10
CONTROL "Use Blend deinterlacing for YUV 4:2:0",IDC_CHECK17,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,219,139,10
GROUPBOX "HDR",IDC_STATIC,171,35,176,94
GROUPBOX "HDR",IDC_STATIC,171,35,176,112
CONTROL "Prefer Dolby Vision over PQ and HLG",IDC_CHECK18,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,178,47,135,10
CONTROL "Passthrough to display",IDC_CHECK12,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,178,60,89,10
LTEXT " if not possible",IDC_STATIC4,178,73,48,8
Expand All @@ -93,12 +93,15 @@ BEGIN
COMBOBOX IDC_COMBO7,232,98,110,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
LTEXT "Subtitle and OSD brightness:",IDC_STATIC6,178,115,99,8
CONTROL "",IDC_SLIDER1,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,279,114,63,12
LTEXT "Swap effect:",IDC_STATIC3,178,134,43,8
COMBOBOX IDC_COMBO4,266,131,76,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
CONTROL "Use exclusive fullscreen",IDC_CHECK11,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,178,147,93,10
CONTROL "Wait for VBlank before Present",IDC_CHECK15,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,178,160,117,10
LTEXT "SDR display nits:",IDC_STATIC8,178,130,60,8
EDITTEXT IDC_EDIT1,242,128,32,14,ES_AUTOHSCROLL | ES_READONLY
CONTROL "",IDC_SPIN1,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,274,128,11,14
LTEXT "Swap effect:",IDC_STATIC3,178,153,43,8
COMBOBOX IDC_COMBO4,266,150,76,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
CONTROL "Use exclusive fullscreen",IDC_CHECK11,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,178,166,93,10
CONTROL "Wait for VBlank before Present",IDC_CHECK15,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,178,179,117,10
CONTROL "Reinitialize device when changing display",IDC_CHECK16,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,178,173,151,10
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,178,192,151,10
PUSHBUTTON "Default",IDC_BUTTON1,305,211,37,14
EDITTEXT IDC_EDIT2,76,235,266,12,ES_READONLY | NOT WS_BORDER,WS_EX_RIGHT
END
Expand Down
28 changes: 25 additions & 3 deletions Source/PropPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ void CVRMainPPage::SetControls()
SendDlgItemMessageW(IDC_COMBO7, CB_SETCURSEL, m_SetsPP.iHdrToggleDisplay, 0);
SendDlgItemMessageW(IDC_SLIDER1, TBM_SETPOS, 1, m_SetsPP.iHdrOsdBrightness);

SendDlgItemMessageW(IDC_SPIN1, UDM_SETRANGE, 0, MAKELONG(400, 25));
SendDlgItemMessageW(IDC_SPIN1, UDM_SETPOS, 0, m_SetsPP.iSDRDisplayNits);

CheckDlgButton(IDC_CHECK6, m_SetsPP.bInterpolateAt50pct ? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(IDC_CHECK10, m_SetsPP.bUseDither ? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(IDC_CHECK17, m_SetsPP.bDeintBlend ? BST_CHECKED : BST_UNCHECKED);
Expand All @@ -117,7 +120,6 @@ void CVRMainPPage::SetControls()
SendDlgItemMessageW(IDC_COMBO5, CB_SETCURSEL, m_SetsPP.iChromaScaling, 0);
SendDlgItemMessageW(IDC_COMBO2, CB_SETCURSEL, m_SetsPP.iUpscaling, 0);
SendDlgItemMessageW(IDC_COMBO3, CB_SETCURSEL, m_SetsPP.iDownscaling, 0);

SendDlgItemMessageW(IDC_COMBO4, CB_SETCURSEL, m_SetsPP.iSwapEffect, 0);
}

Expand Down Expand Up @@ -147,6 +149,10 @@ void CVRMainPPage::EnableControls()
GetDlgItem(IDC_COMBO8).EnableWindow(bEnable && m_SetsPP.bVPScaling);
GetDlgItem(IDC_CHECK19).EnableWindow(bEnable && m_SetsPP.bHdrPassthrough);
}

GetDlgItem(IDC_STATIC8).EnableWindow(m_SetsPP.bConvertToSdr);
GetDlgItem(IDC_EDIT1).EnableWindow(m_SetsPP.bConvertToSdr);
GetDlgItem(IDC_SPIN1).EnableWindow(m_SetsPP.bConvertToSdr);
}

HRESULT CVRMainPPage::OnConnect(IUnknown *pUnk)
Expand Down Expand Up @@ -257,8 +263,9 @@ INT_PTR CVRMainPPage::OnReceiveMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPAR
if (uMsg == WM_COMMAND) {
LRESULT lValue;
const int nID = LOWORD(wParam);
int action = HIWORD(wParam);

if (HIWORD(wParam) == BN_CLICKED) {
if (action == BN_CLICKED) {
if (nID == IDC_CHECK1) {
m_SetsPP.bUseD3D11 = IsDlgButtonChecked(IDC_CHECK1) == BST_CHECKED;
EnableControls();
Expand Down Expand Up @@ -345,6 +352,7 @@ INT_PTR CVRMainPPage::OnReceiveMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPAR
}
if (nID == IDC_CHECK14) {
m_SetsPP.bConvertToSdr = IsDlgButtonChecked(IDC_CHECK14) == BST_CHECKED;
EnableControls();
SetDirty();
return (LRESULT)1;
}
Expand All @@ -363,7 +371,7 @@ INT_PTR CVRMainPPage::OnReceiveMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPAR
}
}

if (HIWORD(wParam) == CBN_SELCHANGE) {
if (action == CBN_SELCHANGE) {
if (nID == IDC_COMBO6) {
lValue = SendDlgItemMessageW(IDC_COMBO6, CB_GETCURSEL, 0, 0);
if (lValue != m_SetsPP.iResizeStats) {
Expand Down Expand Up @@ -432,6 +440,20 @@ INT_PTR CVRMainPPage::OnReceiveMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPAR
}
}
}

if (action == EN_CHANGE) {
if (nID == IDC_EDIT1) {
LRESULT lValue = SendDlgItemMessageW(IDC_SPIN1, UDM_GETPOS, 0, 0);
if (HIWORD(lValue) == 0) { // valid value
int newvalue = LOWORD(lValue);
if (newvalue != m_SetsPP.iSDRDisplayNits) {
m_SetsPP.iSDRDisplayNits = newvalue;
SetDirty();
return (LRESULT)1;
}
}
}
}
}
else if (uMsg == WM_HSCROLL) {
if ((HWND)lParam == GetDlgItem(IDC_SLIDER1)) {
Expand Down
10 changes: 5 additions & 5 deletions Source/Shaders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,7 @@ HRESULT GetShaderConvertColor(
const int chromaScaling,
const int convertType,
const bool blendDeinterlace,
const float LuminanceScale,
ID3DBlob** ppCode)
{
DLog(L"GetShaderConvertColor() started for {} {}x{} extfmt:{:#010x} chroma:{}", fmtParams.str, texW, texH, exFmt.value, chromaScaling);
Expand Down Expand Up @@ -789,14 +790,13 @@ HRESULT GetShaderConvertColor(
"color = LinearToST2084(color, 1000.0);\n"
);
}
code.append(
"#define SRC_LUMINANCE_PEAK 10000.0\n"
"#define DISPLAY_LUMINANCE_PEAK 125.0\n"
std::string hdrtmp = std::format(
"color = saturate(color);\n"
"color = ST2084ToLinear(color, SRC_LUMINANCE_PEAK/DISPLAY_LUMINANCE_PEAK);\n"
"color = ST2084ToLinear(color, {});\n"
"color.rgb = ToneMappingHable(color.rgb);\n"
"color.rgb = mul(matrix_conv_prim, color.rgb);\n"
);
, LuminanceScale);
code.append(hdrtmp);
isLinear = true;
}
else if (bConvertHLGtoPQ) {
Expand Down
Loading

0 comments on commit 524a7d0

Please sign in to comment.