From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/wined3d/adapter_vk.c | 9 +++- dlls/wined3d/decoder.c | 99 ++++++++++++++++++++++++++++++++++ dlls/wined3d/wined3d_private.h | 1 + dlls/wined3d/wined3d_vk.h | 4 ++ include/dxva.h | 7 +++ 5 files changed, 119 insertions(+), 1 deletion(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 1974535e52a..311de30f052 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -2371,6 +2371,11 @@ static bool wined3d_adapter_vk_init_device_extensions(struct wined3d_adapter_vk {VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, VK_API_VERSION_1_1}, {VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, VK_API_VERSION_1_1}, {VK_KHR_SWAPCHAIN_EXTENSION_NAME, ~0u, true}, + /* KHR_synchronization2 is required for KHR_video_queue. */ + {VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME, ~0u}, + {VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME, ~0u}, + {VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME, ~0u}, + {VK_KHR_VIDEO_QUEUE_EXTENSION_NAME, ~0u}, };
static const struct @@ -2391,6 +2396,8 @@ static bool wined3d_adapter_vk_init_device_extensions(struct wined3d_adapter_vk {VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME, WINED3D_VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE}, {VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, WINED3D_VK_KHR_SAMPLER_YCBCR_CONVERSION}, {VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, WINED3D_VK_KHR_SHADER_DRAW_PARAMETERS}, + {VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME, WINED3D_VK_KHR_VIDEO_DECODE_H264}, + {VK_KHR_VIDEO_QUEUE_EXTENSION_NAME, WINED3D_VK_KHR_VIDEO_QUEUE}, };
if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL))) < 0) @@ -2528,7 +2535,7 @@ static BOOL wined3d_adapter_vk_init(struct wined3d_adapter_vk *adapter_vk, adapter->fragment_pipe = wined3d_spirv_fragment_pipe_init_vk(); adapter->misc_state_template = misc_state_template_vk; adapter->shader_backend = wined3d_spirv_shader_backend_init_vk(); - adapter->decoder_ops = &wined3d_null_decoder_ops; + adapter->decoder_ops = &wined3d_decoder_vk_ops;
wined3d_adapter_vk_init_d3d_info(adapter_vk, wined3d_creation_flags);
diff --git a/dlls/wined3d/decoder.c b/dlls/wined3d/decoder.c index 44f36e551da..2da2f5c3c79 100644 --- a/dlls/wined3d/decoder.c +++ b/dlls/wined3d/decoder.c @@ -17,6 +17,9 @@ */
#include "wined3d_private.h" +#include "wined3d_vk.h" + +WINE_DEFAULT_DEBUG_CHANNEL(d3d);
static void wined3d_null_decoder_get_profiles(struct wined3d_adapter *adapter, unsigned int *count, GUID *profiles) { @@ -27,3 +30,99 @@ const struct wined3d_decoder_ops wined3d_null_decoder_ops = { .get_profiles = wined3d_null_decoder_get_profiles, }; + +static void fill_vk_profile_info(VkVideoProfileInfoKHR *profile, const GUID *codec, enum wined3d_format_id format) +{ + profile->sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR; + + if (format == WINED3DFMT_NV12_PLANAR) + { + profile->chromaSubsampling = VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR; + profile->lumaBitDepth = VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR; + profile->chromaBitDepth = VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR; + } + else + { + FIXME("Unhandled output format %s.\n", debug_d3dformat(format)); + } + + if (IsEqualGUID(codec, &DXVA_ModeH264_VLD_NoFGT)) + { + static const VkVideoDecodeH264ProfileInfoKHR h264_profile = + { + .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR, + /* DirectX does not pass profile information anywhere. + * Instead, the DXVA H.264 specification states that streams must + * conform to the High profile. + * + * The actual stream we'll get might be lower profile than that, + * but we have no way of knowing. Even delaying until we get the first + * sample doesn't help us; the profile isn't actually passed in DXVA's + * marshalled PPS/SPS structure either. */ + .stdProfileIdc = STD_VIDEO_H264_PROFILE_IDC_HIGH, + .pictureLayout = VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR, + }; + + profile->pNext = &h264_profile; + profile->videoCodecOperation = VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR; + } + else + { + FIXME("Unhandled codec %s.\n", debugstr_guid(codec)); + } +} + +static bool wined3d_decoder_vk_is_h264_decode_supported(const struct wined3d_adapter_vk *adapter_vk) +{ + VkVideoDecodeH264CapabilitiesKHR h264_caps = {.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_KHR}; + VkVideoDecodeCapabilitiesKHR decode_caps = {.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_CAPABILITIES_KHR}; + VkVideoProfileInfoKHR profile = {.sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR}; + VkVideoCapabilitiesKHR caps = {.sType = VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR}; + const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info; + VkResult vr; + + if (!vk_info->supported[WINED3D_VK_KHR_VIDEO_DECODE_H264]) + return false; + + /* Only NV12 is required to be supported. */ + fill_vk_profile_info(&profile, &DXVA_ModeH264_VLD_NoFGT, WINED3DFMT_NV12_PLANAR); + + caps.pNext = &decode_caps; + decode_caps.pNext = &h264_caps; + if ((vr = VK_CALL(vkGetPhysicalDeviceVideoCapabilitiesKHR( + adapter_vk->physical_device, &profile, &caps))) != VK_SUCCESS) + { + ERR("Failed to query video capabilities, vr %s.\n", wined3d_debug_vkresult(vr)); + return false; + } + + if (!(caps.flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR)) + { + FIXME("Implementation requires a layered DPB.\n"); + return false; + } + + return true; +} + +static void wined3d_decoder_vk_get_profiles(struct wined3d_adapter *adapter, unsigned int *count, GUID *profiles) +{ + const struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk(adapter); + + *count = 0; + + if (!adapter_vk->vk_info.supported[WINED3D_VK_KHR_VIDEO_QUEUE]) + return; + + if (wined3d_decoder_vk_is_h264_decode_supported(adapter_vk)) + { + profiles[(*count)++] = DXVA_ModeH264_VLD_NoFGT; + /* FIXME: Native GPUs also support DXVA2_ModeH264_VLD_Stereo_NoFGT + * and DXVA2_ModeH264_VLD_Stereo_Progressive_NoFGT. */ + } +} + +const struct wined3d_decoder_ops wined3d_decoder_vk_ops = +{ + .get_profiles = wined3d_decoder_vk_get_profiles, +}; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 6ef9ace1345..7b0f6469538 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4468,6 +4468,7 @@ struct wined3d_decoder_ops void (*get_profiles)(struct wined3d_adapter *adapter, unsigned int *count, GUID *profiles); };
+extern const struct wined3d_decoder_ops wined3d_decoder_vk_ops; extern const struct wined3d_decoder_ops wined3d_null_decoder_ops;
/* DirectDraw utility functions */ diff --git a/dlls/wined3d/wined3d_vk.h b/dlls/wined3d/wined3d_vk.h index 1bc40223af6..dd8a1bbfdb0 100644 --- a/dlls/wined3d/wined3d_vk.h +++ b/dlls/wined3d/wined3d_vk.h @@ -53,6 +53,8 @@ struct wined3d_device_vk; VK_INSTANCE_PFN(vkGetPhysicalDeviceSurfaceFormatsKHR) \ VK_INSTANCE_PFN(vkGetPhysicalDeviceSurfacePresentModesKHR) \ VK_INSTANCE_PFN(vkGetPhysicalDeviceSurfaceSupportKHR) \ + /* VK_KHR_video_queue */ \ + VK_INSTANCE_EXT_PFN(vkGetPhysicalDeviceVideoCapabilitiesKHR) \ /* VK_KHR_win32_surface */ \ VK_INSTANCE_PFN(vkCreateWin32SurfaceKHR) \ /* VK_EXT_host_query_reset */ \ @@ -248,6 +250,8 @@ enum wined3d_vk_extension WINED3D_VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE, WINED3D_VK_KHR_SAMPLER_YCBCR_CONVERSION, WINED3D_VK_KHR_SHADER_DRAW_PARAMETERS, + WINED3D_VK_KHR_VIDEO_DECODE_H264, + WINED3D_VK_KHR_VIDEO_QUEUE,
WINED3D_VK_EXT_COUNT, }; diff --git a/include/dxva.h b/include/dxva.h index 9deded52e22..a566c672ae1 100644 --- a/include/dxva.h +++ b/include/dxva.h @@ -99,6 +99,13 @@ DEFINE_GUID(DXVA_ModeJPEG_VLD_444, 0x4cd00e17, 0x89ba, 0x48ef, 0xb9, 0xf9, 0xed,
DEFINE_GUID(DXVA_NoEncrypt, 0x1b81bed0, 0xa0c7,0x11d3, 0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
+#define DXVA_ModeH264_MoComp_NoFGT DXVA_ModeH264_A +#define DXVA_ModeH264_MoComp_FGT DXVA_ModeH264_B +#define DXVA_ModeH264_IDCT_NoFGT DXVA_ModeH264_C +#define DXVA_ModeH264_IDCT_FGT DXVA_ModeH264_D +#define DXVA_ModeH264_VLD_NoFGT DXVA_ModeH264_E +#define DXVA_ModeH264_VLD_FGT DXVA_ModeH264_F + #define DXVA_USUAL_BLOCK_WIDTH 8 #define DXVA_USUAL_BLOCK_HEIGHT 8 #define DXVA_USUAL_BLOCK_SIZE (DXVA_USUAL_BLOCK_WIDTH * DXVA_USUAL_BLOCK_HEIGHT)