diff --git a/src/dxgi/dxgi_interfaces.h b/src/dxgi/dxgi_interfaces.h index 66d517a88..f297e5c36 100644 --- a/src/dxgi/dxgi_interfaces.h +++ b/src/dxgi/dxgi_interfaces.h @@ -2,6 +2,8 @@ #include "../dxvk/dxvk_include.h" +#include "../wsi/wsi_edid.h" + #include "../util/util_time.h" #include "dxgi_format.h" @@ -27,6 +29,7 @@ struct DXGI_VK_MONITOR_DATA { DXGI_FRAME_STATISTICS FrameStats; DXGI_GAMMA_CONTROL GammaCurve; DXGI_MODE_DESC1 LastMode; + dxvk::wsi::WsiDisplayMetadata DisplayMetadata; }; diff --git a/src/dxgi/dxgi_output.cpp b/src/dxgi/dxgi_output.cpp index 23ef7369c..e319b30a1 100644 --- a/src/dxgi/dxgi_output.cpp +++ b/src/dxgi/dxgi_output.cpp @@ -27,23 +27,7 @@ namespace dxvk { : m_monitorInfo(factory->GetMonitorInfo()), m_adapter(adapter), m_monitor(monitor) { - // Query current display mode - wsi::WsiMode activeWsiMode = { }; - wsi::getCurrentDisplayMode(m_monitor, &activeWsiMode); - - // Init monitor info if necessary - DXGI_VK_MONITOR_DATA monitorData = { }; - monitorData.FrameStats.SyncQPCTime.QuadPart = dxvk::high_resolution_clock::get_counter(); - monitorData.GammaCurve.Scale = { 1.0f, 1.0f, 1.0f }; - monitorData.GammaCurve.Offset = { 0.0f, 0.0f, 0.0f }; - monitorData.LastMode = ConvertDisplayMode(activeWsiMode); - - for (uint32_t i = 0; i < DXGI_VK_GAMMA_CP_COUNT; i++) { - const float value = GammaControlPointLocation(i); - monitorData.GammaCurve.GammaCurve[i] = { value, value, value }; - } - - m_monitorInfo->InitMonitorData(monitor, &monitorData); + CacheMonitorData(); } @@ -637,4 +621,53 @@ namespace dxvk { } } + + void DxgiOutput::CacheMonitorData() { + // Try and find an existing monitor info. + DXGI_VK_MONITOR_DATA* pMonitorData; + if (SUCCEEDED(m_monitorInfo->AcquireMonitorData(m_monitor, &pMonitorData))) { + m_metadata = pMonitorData->DisplayMetadata; + return; + } + + // Init monitor info ourselves. + // + // If some other thread ends up beating us to it + // by another InitMonitorData, it doesn't really matter. + // + // The only thing we cache from this is the m_metadata which + // should be exactly the same. + // We don't store any pointers from the DXGI_VK_MONITOR_DATA + // sturcture, etc. + DXGI_VK_MONITOR_DATA monitorData = {}; + + // Query current display mode + wsi::WsiMode activeWsiMode = { }; + wsi::getCurrentDisplayMode(m_monitor, &activeWsiMode); + + // Get the display metadata + colorimetry + wsi::WsiEdidData edidData = wsi::getMonitorEdid(m_monitor); + std::optional metadata = std::nullopt; + if (!edidData.empty()) + metadata = wsi::parseColorimetryInfo(edidData); + + if (metadata) + m_metadata = metadata.value(); + else + Logger::err("DXGI: Failed to parse display metadata + colorimetry info, using blank."); + + monitorData.FrameStats.SyncQPCTime.QuadPart = dxvk::high_resolution_clock::get_counter(); + monitorData.GammaCurve.Scale = { 1.0f, 1.0f, 1.0f }; + monitorData.GammaCurve.Offset = { 0.0f, 0.0f, 0.0f }; + monitorData.LastMode = ConvertDisplayMode(activeWsiMode); + monitorData.DisplayMetadata = m_metadata; + + for (uint32_t i = 0; i < DXGI_VK_GAMMA_CP_COUNT; i++) { + const float value = GammaControlPointLocation(i); + monitorData.GammaCurve.GammaCurve[i] = { value, value, value }; + } + + m_monitorInfo->InitMonitorData(m_monitor, &monitorData); + } + } diff --git a/src/dxgi/dxgi_output.h b/src/dxgi/dxgi_output.h index 0dc30868d..b0f15fa72 100644 --- a/src/dxgi/dxgi_output.h +++ b/src/dxgi/dxgi_output.h @@ -133,10 +133,14 @@ namespace dxvk { Com m_adapter = nullptr; HMONITOR m_monitor = nullptr; + wsi::WsiDisplayMetadata m_metadata = {}; + static void FilterModesByDesc( std::vector& Modes, const DXGI_MODE_DESC1& TargetMode); + void CacheMonitorData(); + }; }