mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2026-03-21 17:49:58 -05:00
Merge 3d1f44c731 into 726f5f8897
This commit is contained in:
commit
ade2e6f97b
|
|
@ -3,6 +3,11 @@
|
|||
/*
|
||||
[configuration]
|
||||
|
||||
[OptionBool]
|
||||
GUIName = Use Display Peak Luminance (DX11+)
|
||||
OptionName = USE_DISPLAY_PEAK_LUMINANCE
|
||||
DefaultValue = 0
|
||||
|
||||
[OptionRangeFloat]
|
||||
GUIName = HDR Display Max Nits
|
||||
OptionName = HDR_DISPLAY_MAX_NITS
|
||||
|
|
@ -54,7 +59,13 @@ void main()
|
|||
// Find the color luminance (it works better than average)
|
||||
float sdr_ratio = luminance(color.rgb);
|
||||
|
||||
const float auto_hdr_max_white = max(HDR_DISPLAY_MAX_NITS / (hdr_paper_white_nits / hdr_sdr_white_nits), hdr_sdr_white_nits) / hdr_sdr_white_nits;
|
||||
// When "Use Display Peak Luminance" is enabled, use the peak luminance reported by the display
|
||||
// (only available on DirectX 11/12). Falls back to the manual slider on other APIs or if
|
||||
// no display data is available.
|
||||
const float display_max_nits = (OptionEnabled(USE_DISPLAY_PEAK_LUMINANCE) && hdr_max_luminance_nits > 0.0)
|
||||
? hdr_max_luminance_nits
|
||||
: HDR_DISPLAY_MAX_NITS;
|
||||
const float auto_hdr_max_white = max(display_max_nits / (hdr_paper_white_nits / hdr_sdr_white_nits), hdr_sdr_white_nits) / hdr_sdr_white_nits;
|
||||
if (sdr_ratio > AUTO_HDR_SHOULDER_START_ALPHA && AUTO_HDR_SHOULDER_START_ALPHA < 1.0)
|
||||
{
|
||||
const float auto_hdr_shoulder_ratio = 1.0 - (max(1.0 - sdr_ratio, 0.0) / (1.0 - AUTO_HDR_SHOULDER_START_ALPHA));
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "VideoCommon/PostProcessing.h"
|
||||
#include "VideoCommon/Present.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
using ConfigurationOption = VideoCommon::PostProcessingConfiguration::ConfigurationOption;
|
||||
using OptionType = ConfigurationOption::OptionType;
|
||||
|
|
@ -43,6 +44,21 @@ PostProcessingConfigWindow::PostProcessingConfigWindow(EnhancementsWidget* paren
|
|||
setWindowTitle(tr("Post-Processing Shader Configuration"));
|
||||
|
||||
PopulateGroups();
|
||||
|
||||
// If the display was queried since the shader was last loaded (e.g. window was resized or
|
||||
// moved to another monitor), sync the slider to the latest queried peak luminance before
|
||||
// building the widgets so the displayed value is always current.
|
||||
if (g_backend_info.hdr_max_luminance_nits > 0.f)
|
||||
{
|
||||
const auto use_peak_it = m_config_map.find("USE_DISPLAY_PEAK_LUMINANCE");
|
||||
const auto max_nits_it = m_config_map.find("HDR_DISPLAY_MAX_NITS");
|
||||
if (use_peak_it != m_config_map.end() && max_nits_it != m_config_map.end() &&
|
||||
use_peak_it->second->GetConfigurationOption()->m_bool_value)
|
||||
{
|
||||
m_post_processor->SetOptionf("HDR_DISPLAY_MAX_NITS", 0, g_backend_info.hdr_max_luminance_nits);
|
||||
}
|
||||
}
|
||||
|
||||
Create();
|
||||
ConnectWidgets();
|
||||
|
||||
|
|
@ -120,6 +136,12 @@ void PostProcessingConfigWindow::Create()
|
|||
m_tabs->insertTab(0, general, tr("General"));
|
||||
}
|
||||
|
||||
// Apply initial enabled state for options controlled by USE_DISPLAY_PEAK_LUMINANCE
|
||||
const auto use_peak_it = m_config_map.find("USE_DISPLAY_PEAK_LUMINANCE");
|
||||
const auto max_nits_it = m_config_map.find("HDR_DISPLAY_MAX_NITS");
|
||||
if (use_peak_it != m_config_map.end() && max_nits_it != m_config_map.end())
|
||||
max_nits_it->second->SetEnabled(!use_peak_it->second->GetCheckboxValue());
|
||||
|
||||
m_buttons = new QDialogButtonBox(QDialogButtonBox::Ok);
|
||||
|
||||
auto* layout = new QVBoxLayout(this);
|
||||
|
|
@ -152,6 +174,14 @@ void PostProcessingConfigWindow::UpdateBool(ConfigGroup* const config_group, con
|
|||
m_post_processor->SetOptionb(config_group->GetOptionName(), state);
|
||||
|
||||
config_group->EnableSuboptions(state);
|
||||
|
||||
if (config_group->GetOptionName() == "USE_DISPLAY_PEAK_LUMINANCE")
|
||||
{
|
||||
m_post_processor->SaveOptionsConfiguration();
|
||||
const auto it = m_config_map.find("HDR_DISPLAY_MAX_NITS");
|
||||
if (it != m_config_map.end())
|
||||
it->second->SetEnabled(!state);
|
||||
}
|
||||
}
|
||||
|
||||
void PostProcessingConfigWindow::UpdateInteger(ConfigGroup* const config_group, const int value)
|
||||
|
|
@ -346,6 +376,14 @@ u32 PostProcessingConfigWindow::ConfigGroup::AddFloat(PostProcessingConfigWindow
|
|||
return row + 1;
|
||||
}
|
||||
|
||||
void PostProcessingConfigWindow::ConfigGroup::SetEnabled(const bool state)
|
||||
{
|
||||
for (auto& slider : m_sliders)
|
||||
slider->setEnabled(state);
|
||||
for (auto& value_box : m_value_boxes)
|
||||
value_box->setEnabled(state);
|
||||
}
|
||||
|
||||
void PostProcessingConfigWindow::ConfigGroup::EnableSuboptions(const bool state)
|
||||
{
|
||||
for (auto& it : m_subgroups)
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ private:
|
|||
const std::vector<std::unique_ptr<ConfigGroup>>& GetSubGroups() const noexcept;
|
||||
u32 AddWidgets(PostProcessingConfigWindow* parent, QGridLayout* grid, u32 row);
|
||||
void EnableSuboptions(bool state);
|
||||
void SetEnabled(bool state);
|
||||
int GetCheckboxValue() const;
|
||||
int GetSliderValue(size_t index) const;
|
||||
void SetSliderText(size_t index, const QString& text);
|
||||
|
|
|
|||
|
|
@ -5,12 +5,15 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <winrt/Windows.Graphics.Display.h>
|
||||
#include <windows.graphics.display.interop.h>
|
||||
|
||||
#include "Common/Assert.h"
|
||||
#include "Common/CommonFuncs.h"
|
||||
#include "Common/HRWrap.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Common/MsgHandler.h"
|
||||
#include "Common/ScopeGuard.h"
|
||||
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
|
|
@ -188,9 +191,52 @@ bool SwapChain::CreateSwapChain(bool stereo, bool hdr)
|
|||
return false;
|
||||
}
|
||||
|
||||
QueryDisplayHDRCapabilities();
|
||||
return true;
|
||||
}
|
||||
|
||||
void SwapChain::QueryDisplayHDRCapabilities()
|
||||
{
|
||||
g_backend_info.hdr_max_luminance_nits = 0.0f;
|
||||
g_backend_info.hdr_min_luminance_nits = 0.0f;
|
||||
g_backend_info.hdr_sdr_white_nits = 80.f;
|
||||
|
||||
if (!m_hdr)
|
||||
return;
|
||||
|
||||
Microsoft::WRL::ComPtr<IDXGIOutput> output;
|
||||
Microsoft::WRL::ComPtr<IDXGIOutput6> output6;
|
||||
DXGI_OUTPUT_DESC1 desc{};
|
||||
|
||||
if (FAILED(m_swap_chain->GetContainingOutput(&output)) || FAILED(output.As(&output6)) ||
|
||||
FAILED(output6->GetDesc1(&desc)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
g_backend_info.hdr_max_luminance_nits = desc.MaxLuminance;
|
||||
g_backend_info.hdr_min_luminance_nits = desc.MinLuminance;
|
||||
|
||||
try
|
||||
{
|
||||
winrt::init_apartment();
|
||||
Common::ScopeGuard uninit_guard([] { winrt::uninit_apartment(); });
|
||||
|
||||
auto statics =
|
||||
winrt::get_activation_factory<winrt::Windows::Graphics::Display::DisplayInformation,
|
||||
IDisplayInformationStaticsInterop>();
|
||||
winrt::Windows::Graphics::Display::DisplayInformation display_info{nullptr};
|
||||
winrt::check_hresult(statics->GetForMonitor(
|
||||
desc.Monitor, winrt::guid_of<winrt::Windows::Graphics::Display::IDisplayInformation>(),
|
||||
winrt::put_abi(display_info)));
|
||||
g_backend_info.hdr_sdr_white_nits = display_info.GetAdvancedColorInfo().SdrWhiteLevelInNits();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
g_backend_info.hdr_sdr_white_nits = 80.f;
|
||||
}
|
||||
}
|
||||
|
||||
void SwapChain::DestroySwapChain()
|
||||
{
|
||||
DestroySwapChainBuffers();
|
||||
|
|
@ -225,7 +271,7 @@ bool SwapChain::ResizeSwapChain()
|
|||
m_width = desc.BufferDesc.Width;
|
||||
m_height = desc.BufferDesc.Height;
|
||||
}
|
||||
|
||||
QueryDisplayHDRCapabilities();
|
||||
return CreateSwapChainBuffers();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <dxgi1_5.h>
|
||||
#include <dxgi1_6.h>
|
||||
#include <wrl/client.h>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
|
@ -54,6 +54,7 @@ protected:
|
|||
u32 GetSwapChainFlags() const;
|
||||
bool CreateSwapChain(bool stereo = false, bool hdr = false);
|
||||
void DestroySwapChain();
|
||||
void QueryDisplayHDRCapabilities();
|
||||
|
||||
virtual bool CreateSwapChainBuffers() = 0;
|
||||
virtual void DestroySwapChainBuffers() = 0;
|
||||
|
|
|
|||
|
|
@ -295,10 +295,32 @@ void PostProcessingConfiguration::LoadOptionsConfiguration()
|
|||
it.second.m_float_values = float_values;
|
||||
}
|
||||
}
|
||||
else if (it.second.m_option_name == "HDR_DISPLAY_MAX_NITS" &&
|
||||
g_backend_info.hdr_max_luminance_nits > 0.f)
|
||||
{
|
||||
it.second.m_float_values[0] = g_backend_info.hdr_max_luminance_nits;
|
||||
it.second.m_dirty = true;
|
||||
std::ostringstream queried_value;
|
||||
queried_value.imbue(std::locale("C"));
|
||||
queried_value << g_backend_info.hdr_max_luminance_nits;
|
||||
ini.GetOrCreateSection(section)->Set(it.second.m_option_name, queried_value.str());
|
||||
ini.Save(File::GetUserPath(F_DOLPHINCONFIG_IDX));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If USE_DISPLAY_PEAK_LUMINANCE is checked and we have queried data, sync the slider to the
|
||||
// queried value so it reflects what the shader is actually using.
|
||||
const auto use_display_peak = m_options.find("USE_DISPLAY_PEAK_LUMINANCE");
|
||||
const auto max_nits_option = m_options.find("HDR_DISPLAY_MAX_NITS");
|
||||
if (use_display_peak != m_options.end() && max_nits_option != m_options.end() &&
|
||||
use_display_peak->second.m_bool_value && g_backend_info.hdr_max_luminance_nits > 0.f)
|
||||
{
|
||||
max_nits_option->second.m_float_values[0] = g_backend_info.hdr_max_luminance_nits;
|
||||
max_nits_option->second.m_dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void PostProcessingConfiguration::SaveOptionsConfiguration()
|
||||
|
|
@ -637,6 +659,8 @@ std::string PostProcessing::GetUniformBufferHeader(bool user_post_process) const
|
|||
ss << " int hdr_output;\n";
|
||||
ss << " float hdr_paper_white_nits;\n";
|
||||
ss << " float hdr_sdr_white_nits;\n";
|
||||
ss << " float hdr_max_luminance_nits;\n";
|
||||
ss << " float hdr_min_luminance_nits;\n";
|
||||
|
||||
if (user_post_process)
|
||||
{
|
||||
|
|
@ -856,6 +880,8 @@ struct BuiltinUniforms
|
|||
s32 hdr_output;
|
||||
float hdr_paper_white_nits;
|
||||
float hdr_sdr_white_nits;
|
||||
float hdr_max_luminance_nits;
|
||||
float hdr_min_luminance_nits;
|
||||
};
|
||||
|
||||
size_t PostProcessing::CalculateUniformsSize(bool user_post_process) const
|
||||
|
|
@ -909,9 +935,19 @@ void PostProcessing::FillUniformBuffer(const MathUtil::Rectangle<int>& src,
|
|||
builtin_uniforms.linear_space_output = m_framebuffer_format == AbstractTextureFormat::RGBA16F;
|
||||
// Implies output values can be beyond the 0-1 range
|
||||
builtin_uniforms.hdr_output = m_framebuffer_format == AbstractTextureFormat::RGBA16F;
|
||||
builtin_uniforms.hdr_paper_white_nits = g_ActiveConfig.color_correction.fHDRPaperWhiteNits;
|
||||
// A value of 1 1 1 usually matches 80 nits in HDR
|
||||
builtin_uniforms.hdr_sdr_white_nits = 80.f;
|
||||
// Clamp paper white to at least the display's SDR white level when display data is available.
|
||||
// This prevents hdr_paper_white (= paper_white_nits / sdr_white_nits) from dropping below 1.0,
|
||||
// which would scale colors up before tone mapping and risk clipping highlights.
|
||||
const float effective_paper_white =
|
||||
g_backend_info.hdr_max_luminance_nits > 0.f ?
|
||||
std::max(g_ActiveConfig.color_correction.fHDRPaperWhiteNits,
|
||||
g_backend_info.hdr_sdr_white_nits) :
|
||||
g_ActiveConfig.color_correction.fHDRPaperWhiteNits;
|
||||
builtin_uniforms.hdr_paper_white_nits = effective_paper_white;
|
||||
// Queried from the display on DX backends; falls back to 80 (scRGB spec value)
|
||||
builtin_uniforms.hdr_sdr_white_nits = g_backend_info.hdr_sdr_white_nits;
|
||||
builtin_uniforms.hdr_max_luminance_nits = g_backend_info.hdr_max_luminance_nits;
|
||||
builtin_uniforms.hdr_min_luminance_nits = g_backend_info.hdr_min_luminance_nits;
|
||||
|
||||
std::memcpy(buffer, &builtin_uniforms, sizeof(builtin_uniforms));
|
||||
buffer += sizeof(builtin_uniforms);
|
||||
|
|
|
|||
|
|
@ -180,6 +180,9 @@ struct BackendInfo
|
|||
bool bSupportsVSLinePointExpand = false;
|
||||
bool bSupportsGLLayerInFS = true;
|
||||
bool bSupportsHDROutput = false;
|
||||
float hdr_max_luminance_nits = 0.f;
|
||||
float hdr_min_luminance_nits = 0.f;
|
||||
float hdr_sdr_white_nits = 80.f;
|
||||
bool bSupportsUnrestrictedDepthRange = false;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user