mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-20 19:54:19 +01:00
[d3d9] Add extended swapchain interfaces
Allows for controling colorspace, etc.
This commit is contained in:
parent
495dc75ab2
commit
f2bb1d4b69
@ -7359,6 +7359,7 @@ namespace dxvk {
|
||||
|
||||
HRESULT D3D9DeviceEx::ResetSwapChain(D3DPRESENT_PARAMETERS* pPresentationParameters, D3DDISPLAYMODEEX* pFullscreenDisplayMode) {
|
||||
D3D9Format backBufferFmt = EnumerateFormat(pPresentationParameters->BackBufferFormat);
|
||||
bool unlockedFormats = m_implicitSwapchain != nullptr && m_implicitSwapchain->HasFormatsUnlocked();
|
||||
|
||||
Logger::info(str::format(
|
||||
"D3D9DeviceEx::ResetSwapChain:\n",
|
||||
@ -7371,7 +7372,7 @@ namespace dxvk {
|
||||
" - Windowed: ", pPresentationParameters->Windowed ? "true" : "false", "\n",
|
||||
" - Swap effect: ", pPresentationParameters->SwapEffect, "\n"));
|
||||
|
||||
if (backBufferFmt != D3D9Format::Unknown) {
|
||||
if (backBufferFmt != D3D9Format::Unknown && !unlockedFormats) {
|
||||
if (!IsSupportedBackBufferFormat(backBufferFmt)) {
|
||||
Logger::err(str::format("D3D9DeviceEx::ResetSwapChain: Unsupported backbuffer format: ",
|
||||
EnumerateFormat(pPresentationParameters->BackBufferFormat)));
|
||||
|
@ -196,12 +196,47 @@ ID3D9VkInteropDevice : public IUnknown {
|
||||
DWORD MapFlags) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief D3D9 current output metadata
|
||||
*/
|
||||
struct D3D9VkExtOutputMetadata {
|
||||
float RedPrimary[2];
|
||||
float GreenPrimary[2];
|
||||
float BluePrimary[2];
|
||||
float WhitePoint[2];
|
||||
float MinLuminance;
|
||||
float MaxLuminance;
|
||||
float MaxFullFrameLuminance;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief D3D9 extended swapchain
|
||||
*/
|
||||
MIDL_INTERFACE("13776e93-4aa9-430a-a4ec-fe9e281181d5")
|
||||
ID3D9VkExtSwapchain : public IUnknown {
|
||||
virtual BOOL STDMETHODCALLTYPE CheckColorSpaceSupport(
|
||||
VkColorSpaceKHR ColorSpace) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE SetColorSpace(
|
||||
VkColorSpaceKHR ColorSpace) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE SetHDRMetaData(
|
||||
const VkHdrMetadataEXT *pHDRMetadata) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetCurrentOutputDesc(
|
||||
D3D9VkExtOutputMetadata *pOutputDesc) = 0;
|
||||
|
||||
virtual void STDMETHODCALLTYPE UnlockAdditionalFormats() = 0;
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
struct __declspec(uuid("3461a81b-ce41-485b-b6b5-fcf08ba6a6bd")) ID3D9VkInteropInterface;
|
||||
struct __declspec(uuid("d56344f5-8d35-46fd-806d-94c351b472c1")) ID3D9VkInteropTexture;
|
||||
struct __declspec(uuid("2eaa4b89-0107-4bdb-87f7-0f541c493ce0")) ID3D9VkInteropDevice;
|
||||
struct __declspec(uuid("13776e93-4aa9-430a-a4ec-fe9e281181d5")) ID3D9VkExtSwapchain;
|
||||
#else
|
||||
__CRT_UUID_DECL(ID3D9VkInteropInterface, 0x3461a81b,0xce41,0x485b,0xb6,0xb5,0xfc,0xf0,0x8b,0xa6,0xa6,0xbd);
|
||||
__CRT_UUID_DECL(ID3D9VkInteropTexture, 0xd56344f5,0x8d35,0x46fd,0x80,0x6d,0x94,0xc3,0x51,0xb4,0x72,0xc1);
|
||||
__CRT_UUID_DECL(ID3D9VkInteropDevice, 0x2eaa4b89,0x0107,0x4bdb,0x87,0xf7,0x0f,0x54,0x1c,0x49,0x3c,0xe0);
|
||||
__CRT_UUID_DECL(ID3D9VkExtSwapchain, 0x13776e93,0x4aa9,0x430a,0xa4,0xec,0xfe,0x9e,0x28,0x11,0x81,0xd5);
|
||||
#endif
|
||||
|
@ -29,7 +29,8 @@ namespace dxvk {
|
||||
, m_context (m_device->createContext(DxvkContextType::Supplementary))
|
||||
, m_frameLatencyCap (pDevice->GetOptions()->maxFrameLatency)
|
||||
, m_frameLatencySignal(new sync::Fence(m_frameId))
|
||||
, m_dialog (pDevice->GetOptions()->enableDialogMode) {
|
||||
, m_dialog (pDevice->GetOptions()->enableDialogMode)
|
||||
, m_swapchainExt (this) {
|
||||
this->NormalizePresentParameters(pPresentParams);
|
||||
m_presentParams = *pPresentParams;
|
||||
m_window = m_presentParams.hDeviceWindow;
|
||||
@ -86,6 +87,11 @@ namespace dxvk {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (riid == __uuidof(ID3D9VkExtSwapchain)) {
|
||||
*ppvObject = ref(&m_swapchainExt);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (logQueryInterfaceError(__uuidof(IDirect3DSwapChain9), riid)) {
|
||||
Logger::warn("D3D9SwapChainEx::QueryInterface: Unknown interface query");
|
||||
Logger::warn(str::format(riid));
|
||||
@ -762,6 +768,11 @@ namespace dxvk {
|
||||
status = m_presenter->acquireNextImage(sync, imageIndex);
|
||||
}
|
||||
|
||||
if (m_hdrMetadata && m_dirtyHdrMetadata) {
|
||||
m_presenter->setHdrMetadata(*m_hdrMetadata);
|
||||
m_dirtyHdrMetadata = false;
|
||||
}
|
||||
|
||||
m_context->beginRecording(
|
||||
m_device->createCommandList());
|
||||
|
||||
@ -1086,27 +1097,36 @@ namespace dxvk {
|
||||
case D3D9Format::X8R8G8B8:
|
||||
case D3D9Format::A8B8G8R8:
|
||||
case D3D9Format::X8B8G8R8: {
|
||||
pDstFormats[n++] = { VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
|
||||
pDstFormats[n++] = { VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
|
||||
pDstFormats[n++] = { VK_FORMAT_R8G8B8A8_UNORM, m_colorspace };
|
||||
pDstFormats[n++] = { VK_FORMAT_B8G8R8A8_UNORM, m_colorspace };
|
||||
} break;
|
||||
|
||||
case D3D9Format::A2R10G10B10:
|
||||
case D3D9Format::A2B10G10R10: {
|
||||
pDstFormats[n++] = { VK_FORMAT_A2B10G10R10_UNORM_PACK32, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
|
||||
pDstFormats[n++] = { VK_FORMAT_A2R10G10B10_UNORM_PACK32, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
|
||||
pDstFormats[n++] = { VK_FORMAT_A2B10G10R10_UNORM_PACK32, m_colorspace };
|
||||
pDstFormats[n++] = { VK_FORMAT_A2R10G10B10_UNORM_PACK32, m_colorspace };
|
||||
} break;
|
||||
|
||||
case D3D9Format::X1R5G5B5:
|
||||
case D3D9Format::A1R5G5B5: {
|
||||
pDstFormats[n++] = { VK_FORMAT_B5G5R5A1_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
|
||||
pDstFormats[n++] = { VK_FORMAT_R5G5B5A1_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
|
||||
pDstFormats[n++] = { VK_FORMAT_A1R5G5B5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
|
||||
pDstFormats[n++] = { VK_FORMAT_B5G5R5A1_UNORM_PACK16, m_colorspace };
|
||||
pDstFormats[n++] = { VK_FORMAT_R5G5B5A1_UNORM_PACK16, m_colorspace };
|
||||
pDstFormats[n++] = { VK_FORMAT_A1R5G5B5_UNORM_PACK16, m_colorspace };
|
||||
} break;
|
||||
|
||||
case D3D9Format::R5G6B5: {
|
||||
pDstFormats[n++] = { VK_FORMAT_B5G6R5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
|
||||
pDstFormats[n++] = { VK_FORMAT_R5G6B5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
|
||||
pDstFormats[n++] = { VK_FORMAT_B5G6R5_UNORM_PACK16, m_colorspace };
|
||||
pDstFormats[n++] = { VK_FORMAT_R5G6B5_UNORM_PACK16, m_colorspace };
|
||||
} break;
|
||||
|
||||
case D3D9Format::A16B16G16R16F: {
|
||||
if (m_unlockAdditionalFormats) {
|
||||
pDstFormats[n++] = { VK_FORMAT_R16G16B16A16_SFLOAT, m_colorspace };
|
||||
} else {
|
||||
Logger::warn(str::format("D3D9SwapChainEx: Unexpected format: ", Format));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
@ -1303,4 +1323,91 @@ namespace dxvk {
|
||||
return this->GetParent()->IsExtended() ? "D3D9Ex" : "D3D9";
|
||||
}
|
||||
|
||||
D3D9VkExtSwapchain::D3D9VkExtSwapchain(D3D9SwapChainEx *pSwapChain)
|
||||
: m_swapchain(pSwapChain) {
|
||||
|
||||
}
|
||||
|
||||
ULONG STDMETHODCALLTYPE D3D9VkExtSwapchain::AddRef() {
|
||||
return m_swapchain->AddRef();
|
||||
}
|
||||
|
||||
ULONG STDMETHODCALLTYPE D3D9VkExtSwapchain::Release() {
|
||||
return m_swapchain->Release();
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE D3D9VkExtSwapchain::QueryInterface(
|
||||
REFIID riid,
|
||||
void** ppvObject) {
|
||||
return m_swapchain->QueryInterface(riid, ppvObject);
|
||||
}
|
||||
|
||||
BOOL STDMETHODCALLTYPE D3D9VkExtSwapchain::CheckColorSpaceSupport(
|
||||
VkColorSpaceKHR ColorSpace) {
|
||||
return m_swapchain->m_presenter->supportsColorSpace(ColorSpace);
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE D3D9VkExtSwapchain::SetColorSpace(
|
||||
VkColorSpaceKHR ColorSpace) {
|
||||
if (!CheckColorSpaceSupport(ColorSpace))
|
||||
return D3DERR_INVALIDCALL;
|
||||
|
||||
m_swapchain->m_dirty |= ColorSpace != m_swapchain->m_colorspace;
|
||||
m_swapchain->m_colorspace = ColorSpace;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE D3D9VkExtSwapchain::SetHDRMetaData(
|
||||
const VkHdrMetadataEXT *pHDRMetadata) {
|
||||
if (!pHDRMetadata)
|
||||
return D3DERR_INVALIDCALL;
|
||||
|
||||
m_swapchain->m_hdrMetadata = *pHDRMetadata;
|
||||
m_swapchain->m_dirtyHdrMetadata = true;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE D3D9VkExtSwapchain::GetCurrentOutputDesc(
|
||||
D3D9VkExtOutputMetadata *pOutputDesc) {
|
||||
HMONITOR monitor = m_swapchain->m_monitor;
|
||||
if (!monitor)
|
||||
monitor = wsi::getDefaultMonitor();
|
||||
// ^ this should be the display we are mostly covering someday.
|
||||
|
||||
wsi::WsiEdidData edidData = wsi::getMonitorEdid(monitor);
|
||||
wsi::WsiDisplayMetadata metadata = {};
|
||||
{
|
||||
std::optional<wsi::WsiDisplayMetadata> r_metadata = std::nullopt;
|
||||
if (!edidData.empty())
|
||||
r_metadata = wsi::parseColorimetryInfo(edidData);
|
||||
|
||||
if (r_metadata)
|
||||
metadata = *r_metadata;
|
||||
else
|
||||
Logger::err("D3D9: Failed to parse display metadata + colorimetry info, using blank.");
|
||||
}
|
||||
|
||||
|
||||
NormalizeDisplayMetadata(CheckColorSpaceSupport(VK_COLOR_SPACE_HDR10_ST2084_EXT), metadata);
|
||||
|
||||
pOutputDesc->RedPrimary[0] = metadata.redPrimary[0];
|
||||
pOutputDesc->RedPrimary[1] = metadata.redPrimary[1];
|
||||
pOutputDesc->GreenPrimary[0] = metadata.greenPrimary[0];
|
||||
pOutputDesc->GreenPrimary[1] = metadata.greenPrimary[1];
|
||||
pOutputDesc->BluePrimary[0] = metadata.bluePrimary[0];
|
||||
pOutputDesc->BluePrimary[1] = metadata.bluePrimary[1];
|
||||
pOutputDesc->WhitePoint[0] = metadata.whitePoint[0];
|
||||
pOutputDesc->WhitePoint[1] = metadata.whitePoint[1];
|
||||
pOutputDesc->MinLuminance = metadata.minLuminance;
|
||||
pOutputDesc->MaxLuminance = metadata.maxLuminance;
|
||||
pOutputDesc->MaxFullFrameLuminance = metadata.maxFullFrameLuminance;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void STDMETHODCALLTYPE D3D9VkExtSwapchain::UnlockAdditionalFormats() {
|
||||
m_swapchain->m_unlockAdditionalFormats = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,10 +18,43 @@
|
||||
namespace dxvk {
|
||||
|
||||
class D3D9Surface;
|
||||
class D3D9SwapChainEx;
|
||||
|
||||
class D3D9VkExtSwapchain final : public ID3D9VkExtSwapchain {
|
||||
public:
|
||||
D3D9VkExtSwapchain(D3D9SwapChainEx *pSwapChain);
|
||||
|
||||
ULONG STDMETHODCALLTYPE AddRef();
|
||||
|
||||
ULONG STDMETHODCALLTYPE Release();
|
||||
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(
|
||||
REFIID riid,
|
||||
void** ppvObject);
|
||||
|
||||
BOOL STDMETHODCALLTYPE CheckColorSpaceSupport(
|
||||
VkColorSpaceKHR ColorSpace);
|
||||
|
||||
HRESULT STDMETHODCALLTYPE SetColorSpace(
|
||||
VkColorSpaceKHR ColorSpace);
|
||||
|
||||
HRESULT STDMETHODCALLTYPE SetHDRMetaData(
|
||||
const VkHdrMetadataEXT *pHDRMetadata);
|
||||
|
||||
HRESULT STDMETHODCALLTYPE GetCurrentOutputDesc(
|
||||
D3D9VkExtOutputMetadata *pOutputDesc);
|
||||
|
||||
void STDMETHODCALLTYPE UnlockAdditionalFormats();
|
||||
|
||||
private:
|
||||
D3D9SwapChainEx *m_swapchain;
|
||||
};
|
||||
|
||||
using D3D9SwapChainExBase = D3D9DeviceChild<IDirect3DSwapChain9Ex>;
|
||||
class D3D9SwapChainEx final : public D3D9SwapChainExBase {
|
||||
static constexpr uint32_t NumControlPoints = 256;
|
||||
|
||||
friend class D3D9VkExtSwapchain;
|
||||
public:
|
||||
|
||||
D3D9SwapChainEx(
|
||||
@ -85,6 +118,8 @@ namespace dxvk {
|
||||
|
||||
void SyncFrameLatency();
|
||||
|
||||
bool HasFormatsUnlocked() const { return m_unlockAdditionalFormats; }
|
||||
|
||||
private:
|
||||
|
||||
enum BindingIds : uint32_t {
|
||||
@ -134,6 +169,14 @@ namespace dxvk {
|
||||
|
||||
bool m_warnedAboutGDIFallback = false;
|
||||
|
||||
VkColorSpaceKHR m_colorspace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
|
||||
|
||||
std::optional<VkHdrMetadataEXT> m_hdrMetadata;
|
||||
bool m_dirtyHdrMetadata = true;
|
||||
bool m_unlockAdditionalFormats = false;
|
||||
|
||||
D3D9VkExtSwapchain m_swapchainExt;
|
||||
|
||||
void PresentImage(UINT PresentInterval);
|
||||
|
||||
void SubmitPresent(const vk::PresenterSync& Sync, uint32_t FrameId);
|
||||
|
Loading…
x
Reference in New Issue
Block a user