diff --git a/src/d3d11/d3d11_swapchain.cpp b/src/d3d11/d3d11_swapchain.cpp index 7e489f147..2fc84ab49 100644 --- a/src/d3d11/d3d11_swapchain.cpp +++ b/src/d3d11/d3d11_swapchain.cpp @@ -322,10 +322,8 @@ namespace dxvk { HRESULT STDMETHODCALLTYPE D3D11SwapChain::SetHDRMetaData( const DXGI_VK_HDR_METADATA* pMetaData) { // For some reason this call always seems to succeed on Windows - if (pMetaData->Type == DXGI_HDR_METADATA_TYPE_HDR10) { - m_hdrMetadata = ConvertHDRMetadata(pMetaData->HDR10); - m_dirtyHdrMetadata = true; - } + if (pMetaData->Type == DXGI_HDR_METADATA_TYPE_HDR10) + m_presenter->setHdrMetadata(ConvertHDRMetadata(pMetaData->HDR10)); return S_OK; } @@ -402,11 +400,6 @@ namespace dxvk { break; } - if (m_hdrMetadata && m_dirtyHdrMetadata) { - m_presenter->setHdrMetadata(*m_hdrMetadata); - m_dirtyHdrMetadata = false; - } - m_frameId += 1; // Present from CS thread so that we don't @@ -501,7 +494,6 @@ namespace dxvk { m_device->waitForIdle(); m_presentStatus.result = VK_SUCCESS; - m_dirtyHdrMetadata = true; PresenterDesc presenterDesc; presenterDesc.imageExtent = { m_desc.Width, m_desc.Height }; diff --git a/src/d3d11/d3d11_swapchain.h b/src/d3d11/d3d11_swapchain.h index 6766701f8..80e8dfb81 100644 --- a/src/d3d11/d3d11_swapchain.h +++ b/src/d3d11/d3d11_swapchain.h @@ -123,9 +123,6 @@ namespace dxvk { VkColorSpaceKHR m_colorspace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; - std::optional m_hdrMetadata; - bool m_dirtyHdrMetadata = true; - double m_targetFrameRate = 0.0; dxvk::mutex m_frameStatisticsLock; diff --git a/src/dxvk/dxvk_presenter.cpp b/src/dxvk/dxvk_presenter.cpp index 224b8d97f..a97c60200 100644 --- a/src/dxvk/dxvk_presenter.cpp +++ b/src/dxvk/dxvk_presenter.cpp @@ -72,7 +72,18 @@ namespace dxvk { if (m_acquireStatus != VK_SUCCESS && m_acquireStatus != VK_SUBOPTIMAL_KHR) return m_acquireStatus; - + + // Update HDR metadata after a successful acquire. We know + // that there won't be a present in flight at this point. + if (m_hdrMetadataDirty && m_hdrMetadata) { + m_hdrMetadataDirty = false; + + if (m_device->features().extHdrMetadata) { + m_vkd->vkSetHdrMetadataEXT(m_vkd->device(), + 1, &m_swapchain, &(*m_hdrMetadata)); + } + } + image = m_images.at(m_imageIndex); return m_acquireStatus; } @@ -415,6 +426,8 @@ namespace dxvk { } // Invalidate indices + m_hdrMetadataDirty = true; + m_imageIndex = 0; m_frameIndex = 0; m_acquireStatus = VK_NOT_READY; @@ -464,8 +477,18 @@ namespace dxvk { void Presenter::setHdrMetadata(const VkHdrMetadataEXT& hdrMetadata) { - if (m_device->features().extHdrMetadata) - m_vkd->vkSetHdrMetadataEXT(m_vkd->device(), 1, &m_swapchain, &hdrMetadata); + if (m_hdrMetadata->sType != VK_STRUCTURE_TYPE_HDR_METADATA_EXT) { + m_hdrMetadata = std::nullopt; + return; + } + + if (hdrMetadata.pNext) + Logger::warn("HDR metadata extensions not currently supported."); + + m_hdrMetadata = hdrMetadata; + m_hdrMetadata->pNext = nullptr; + + m_hdrMetadataDirty = true; } diff --git a/src/dxvk/dxvk_presenter.h b/src/dxvk/dxvk_presenter.h index e10ca91af..2da3a78ca 100644 --- a/src/dxvk/dxvk_presenter.h +++ b/src/dxvk/dxvk_presenter.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -190,16 +191,17 @@ namespace dxvk { } /** - * \brief Checks if a presenter supports the colorspace + * \brief Checks support for a Vulkan color space * - * \param [in] colorspace The colorspace to test - * * \returns \c true if the presenter supports the colorspace + * \param [in] colorspace The color space to test + * \returns \c true if the Vulkan surface supports the colorspace */ bool supportsColorSpace(VkColorSpaceKHR colorspace); /** * \brief Sets HDR metadata * + * Updated HDR metadata will be applied on the next \c acquire. * \param [in] hdrMetadata HDR Metadata */ void setHdrMetadata(const VkHdrMetadataEXT& hdrMetadata); @@ -230,6 +232,9 @@ namespace dxvk { VkResult m_acquireStatus = VK_NOT_READY; + std::optional m_hdrMetadata; + bool m_hdrMetadataDirty = false; + alignas(CACHE_LINE_SIZE) dxvk::mutex m_frameMutex; dxvk::condition_variable m_frameCond;