[dxgi] Implement DXGIOutput::GetDesc1's ColorSpace

Adds the ability to punt the global colorspace into HDR from SetColorSpace1.

We have no way of checking the actual Windows colorspace as the
only public method for this *is* DXGI which we are re-implementing.
So we just pick our color space based on the DXVK_HDR env var
and the punting from SetColorSpace1.

We might expand on this in future, but this is good enough for an
initial implementation.
This commit is contained in:
Joshua Ashton 2023-01-03 13:49:59 +00:00 committed by Philip Rebohle
parent dd660585c0
commit f453d6ee2a
5 changed files with 64 additions and 12 deletions

View File

@ -200,6 +200,30 @@ IDXGIVkMonitorInfo : public IUnknown {
*/
virtual void STDMETHODCALLTYPE ReleaseMonitorData() = 0;
/**
* \brief Punt global colorspace
*
* This exists to satiate a requirement for
* IDXGISwapChain::SetColorSpace1 punting Windows into
* the global "HDR mode".
*
* This operation is atomic and does not require
* owning any monitor data.
*
* \param [in] ColorSpace The colorspace
*/
virtual void STDMETHODCALLTYPE PuntColorSpace(DXGI_COLOR_SPACE_TYPE ColorSpace) = 0;
/**
* \brief Get current global colorspace
*
* This operation is atomic and does not require
* owning any monitor data.
*
* \returns Current global colorspace
*/
virtual DXGI_COLOR_SPACE_TYPE STDMETHODCALLTYPE CurrentColorSpace() const = 0;
};

View File

@ -3,7 +3,8 @@
namespace dxvk {
DxgiMonitorInfo::DxgiMonitorInfo(IUnknown* pParent)
: m_parent(pParent) {
: m_parent(pParent)
, m_globalColorSpace(DefaultColorSpace()) {
}
@ -69,6 +70,23 @@ namespace dxvk {
}
void STDMETHODCALLTYPE DxgiMonitorInfo::PuntColorSpace(DXGI_COLOR_SPACE_TYPE ColorSpace) {
m_globalColorSpace = ColorSpace;
}
DXGI_COLOR_SPACE_TYPE STDMETHODCALLTYPE DxgiMonitorInfo::CurrentColorSpace() const {
return m_globalColorSpace;
}
DXGI_COLOR_SPACE_TYPE DxgiMonitorInfo::DefaultColorSpace() {
return env::getEnvVar("DXVK_HDR") == "1"
? DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020
: DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
}
uint32_t GetMonitorFormatBpp(DXGI_FORMAT Format) {
switch (Format) {
case DXGI_FORMAT_R8G8B8A8_UNORM:

View File

@ -37,6 +37,12 @@ namespace dxvk {
void STDMETHODCALLTYPE ReleaseMonitorData();
void STDMETHODCALLTYPE PuntColorSpace(DXGI_COLOR_SPACE_TYPE ColorSpace);
DXGI_COLOR_SPACE_TYPE STDMETHODCALLTYPE CurrentColorSpace() const;
static DXGI_COLOR_SPACE_TYPE DefaultColorSpace();
private:
IUnknown* m_parent;
@ -44,6 +50,8 @@ namespace dxvk {
dxvk::mutex m_monitorMutex;
std::unordered_map<HMONITOR, DXGI_VK_MONITOR_DATA> m_monitorData;
std::atomic<DXGI_COLOR_SPACE_TYPE> m_globalColorSpace;
};

View File

@ -218,21 +218,17 @@ namespace dxvk {
pDesc->AttachedToDesktop = 1;
pDesc->Rotation = DXGI_MODE_ROTATION_UNSPECIFIED;
pDesc->Monitor = m_monitor;
// TODO: When in HDR, flip this to 10 to appease apps that the
// transition has occured.
// If we support more than HDR10 in future, then we may want
// to visit that assumption.
pDesc->BitsPerColor = 8;
// This should only return DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020
// (HDR) if the user has the HDR setting enabled in Windows.
// Games can still punt into HDR mode by using CheckColorSpaceSupport
// and SetColorSpace1.
//
// TODO: When we have a swapchain using SetColorSpace1 to
// DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020, we should use our monitor
// info to flip this over to that.
// As on Windows this would automatically engage HDR mode.
pDesc->ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
//
// We have no way of checking the actual Windows colorspace as the
// only public method for this *is* DXGI which we are re-implementing.
// So we just pick our color space based on the DXVK_HDR env var
// and the punting from SetColorSpace1.
pDesc->ColorSpace = m_monitorInfo->CurrentColorSpace();
pDesc->RedPrimary[0] = m_metadata.redPrimary[0];
pDesc->RedPrimary[1] = m_metadata.redPrimary[1];
pDesc->GreenPrimary[0] = m_metadata.greenPrimary[0];

View File

@ -536,7 +536,13 @@ namespace dxvk {
return E_INVALIDARG;
std::lock_guard<dxvk::mutex> lock(m_lockBuffer);
return m_presenter->SetColorSpace(ColorSpace);
HRESULT hr = m_presenter->SetColorSpace(ColorSpace);
if (SUCCEEDED(hr)) {
// If this was a colorspace other than our current one,
// punt us into that one on the DXGI output.
m_monitorInfo->PuntColorSpace(ColorSpace);
}
return hr;
}