Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/HansKristian-Work/vkd3d-proton.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Ashton <joshua@froggi.es>2022-09-09 22:28:54 +0300
committerHans-Kristian Arntzen <post@arntzen-software.no>2022-09-16 15:11:07 +0300
commit60d139d34fb4accafa52df48486d20fbc83f85b2 (patch)
treea23c2e3709fae5f9d219a04c43de6a6b477d84ae
parent95d2c8f2352cc6da2111d29c2b9c216eb7bbcbd4 (diff)
vkd3d: Implement SetHDRMetaData
-rw-r--r--libs/vkd3d/swapchain.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/libs/vkd3d/swapchain.c b/libs/vkd3d/swapchain.c
index 25881150..3fc18a7d 100644
--- a/libs/vkd3d/swapchain.c
+++ b/libs/vkd3d/swapchain.c
@@ -219,6 +219,9 @@ struct d3d12_swapchain
uint64_t frame_number;
uint32_t frame_latency;
uint32_t frame_id;
+
+ DXGI_HDR_METADATA_TYPE hdr_metadata_type;
+ VkHdrMetadataEXT hdr_metadata;
};
static inline const struct vkd3d_vk_device_procs* d3d12_swapchain_procs(struct d3d12_swapchain* swapchain)
@@ -1409,6 +1412,19 @@ static bool d3d12_swapchain_has_nonzero_surface_size(struct d3d12_swapchain *swa
return surface_caps.maxImageExtent.width != 0 && surface_caps.maxImageExtent.height != 0;
}
+static void d3d12_swapchain_set_hdr_metadata(struct d3d12_swapchain *swapchain)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = d3d12_swapchain_procs(swapchain);
+
+ if (!swapchain->command_queue->device->vk_info.EXT_hdr_metadata)
+ return;
+
+ if (swapchain->hdr_metadata_type == DXGI_HDR_METADATA_TYPE_NONE)
+ return;
+
+ VK_CALL(vkSetHdrMetadataEXT(swapchain->command_queue->device->vk_device, 1, &swapchain->vk_swapchain, &swapchain->hdr_metadata));
+}
+
static HRESULT d3d12_swapchain_create_vulkan_swapchain(struct d3d12_swapchain *swapchain, bool force_surface_lost)
{
VkPhysicalDevice vk_physical_device = d3d12_swapchain_device(swapchain)->vk_physical_device;
@@ -1595,6 +1611,7 @@ static HRESULT d3d12_swapchain_create_vulkan_swapchain(struct d3d12_swapchain *s
return hr;
}
+ d3d12_swapchain_set_hdr_metadata(swapchain);
return d3d12_swapchain_create_buffers(swapchain, vk_swapchain_format, vk_format);
}
else
@@ -2686,28 +2703,114 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_ResizeBuffers1(dxgi_swapchain_i
return hr;
}
+static void d3d12_swapchain_update_hdr_metadata(struct d3d12_swapchain *swapchain, DXGI_HDR_METADATA_TYPE metadata_type, VkHdrMetadataEXT *metadata)
+{
+ if (swapchain->hdr_metadata_type == metadata_type)
+ return;
+
+ swapchain->hdr_metadata_type = metadata_type;
+
+ if (!swapchain->command_queue->device->vk_info.EXT_hdr_metadata)
+ return;
+
+ if (metadata)
+ {
+ assert(metadata_type == DXGI_HDR_METADATA_TYPE_HDR10);
+
+ swapchain->hdr_metadata = *metadata;
+ d3d12_swapchain_set_hdr_metadata(swapchain);
+ }
+ else
+ {
+ assert(metadata_type == DXGI_HDR_METADATA_TYPE_NONE);
+
+ /* If we are DXGI_HDR_METADATA_TYPE_NONE, we must clear the metadata.
+ * The D3D docs do not mention this, but the sample does!
+ * We have no way of doing this easily in Vulkan, aside from just
+ * re-creating the swapchain. */
+ d3d12_swapchain_destroy_resources(swapchain, false);
+ d3d12_swapchain_create_vulkan_swapchain(swapchain, false);
+ }
+}
+
+static VkXYColorEXT convert_xy_color(UINT16 *dxgi_color)
+{
+ return (VkXYColorEXT){ dxgi_color[0] / 50000.0f, dxgi_color[1] / 50000.0f };
+}
+
+static float convert_max_luminance(UINT dxgi_luminance)
+{
+ /* The documentation says this is in *whole* nits, but this
+ * contradicts the HEVC standard it claims to mirror,
+ * and the sample's behaviour.
+ * We should come back and validate this once
+ * https://github.com/microsoft/DirectX-Graphics-Samples/issues/796
+ * has an answer. */
+ return (float)dxgi_luminance;
+}
+
+static float convert_min_luminance(UINT dxgi_luminance)
+{
+ return dxgi_luminance / 0.0001f;
+}
+
+static float convert_level(UINT16 dxgi_level)
+{
+ return (float)dxgi_level;
+}
+
+static VkHdrMetadataEXT convert_hdr_metadata_hdr10(DXGI_HDR_METADATA_HDR10 *dxgi_metadata)
+{
+ VkHdrMetadataEXT vulkan_metadata = { VK_STRUCTURE_TYPE_HDR_METADATA_EXT };
+ vulkan_metadata.displayPrimaryRed = convert_xy_color(dxgi_metadata->RedPrimary);
+ vulkan_metadata.displayPrimaryGreen = convert_xy_color(dxgi_metadata->GreenPrimary);
+ vulkan_metadata.displayPrimaryBlue = convert_xy_color(dxgi_metadata->BluePrimary);
+ vulkan_metadata.whitePoint = convert_xy_color(dxgi_metadata->WhitePoint);
+ vulkan_metadata.maxLuminance = convert_max_luminance(dxgi_metadata->MaxMasteringLuminance);
+ vulkan_metadata.minLuminance = convert_min_luminance(dxgi_metadata->MinMasteringLuminance);
+ vulkan_metadata.maxContentLightLevel = convert_level(dxgi_metadata->MaxContentLightLevel);
+ vulkan_metadata.maxFrameAverageLightLevel = convert_level(dxgi_metadata->MaxFrameAverageLightLevel);
+ return vulkan_metadata;
+}
+
static HRESULT STDMETHODCALLTYPE d3d12_swapchain_SetHDRMetaData(dxgi_swapchain_iface *iface,
DXGI_HDR_METADATA_TYPE type, UINT size, void *metadata)
{
+ struct d3d12_swapchain *swapchain = d3d12_swapchain_from_IDXGISwapChain(iface);
+ VkHdrMetadataEXT vulkan_metadata;
+
FIXME("iface %p, type %u, size %u, metadata %p semi-stub!", iface, type, size, metadata);
if (size && !metadata)
return E_INVALIDARG;
+ EnterCriticalSection(&swapchain->mutex);
+
switch (type)
{
case DXGI_HDR_METADATA_TYPE_NONE:
+ d3d12_swapchain_update_hdr_metadata(swapchain, type, NULL);
+ LeaveCriticalSection(&swapchain->mutex);
return S_OK;
case DXGI_HDR_METADATA_TYPE_HDR10:
if (size != sizeof(DXGI_HDR_METADATA_HDR10))
return E_INVALIDARG;
+ vulkan_metadata = convert_hdr_metadata_hdr10((DXGI_HDR_METADATA_HDR10 *)metadata);
+ d3d12_swapchain_update_hdr_metadata(swapchain, type, &vulkan_metadata);
+
/* For some reason this always seems to succeed on Windows */
+ LeaveCriticalSection(&swapchain->mutex);
return S_OK;
default:
FIXME("Unsupported HDR metadata type %u.\n", type);
+
+ /* Specify this as as call to NONE for now, as it isn't implemented.
+ * This has the least chance of breaking things. */
+ d3d12_swapchain_update_hdr_metadata(swapchain, DXGI_HDR_METADATA_TYPE_NONE, NULL);
+ LeaveCriticalSection(&swapchain->mutex);
return E_INVALIDARG;
}
}