-- v2: wined3d: Create a Vulkan video session backing the wined3d_decoder_vk. wined3d: Look for a video decode queue. d3d11: Create a wined3d_decoder object backing the d3d11 decoder object. wined3d: Introduce a Vulkan decoder backend.
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/d3d11/device.c | 14 ++++++++++---- dlls/wined3d/Makefile.in | 1 + dlls/wined3d/adapter_gl.c | 1 + dlls/wined3d/adapter_vk.c | 1 + dlls/wined3d/decoder.c | 29 +++++++++++++++++++++++++++++ dlls/wined3d/device.c | 27 +++++++++++++++++++++++++++ dlls/wined3d/directx.c | 1 + dlls/wined3d/wined3d.spec | 2 ++ dlls/wined3d/wined3d_private.h | 11 +++++++++++ include/wine/wined3d.h | 2 ++ 10 files changed, 85 insertions(+), 4 deletions(-) create mode 100644 dlls/wined3d/decoder.c
diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c index 5c819f4e983..9d4c137b3de 100644 --- a/dlls/d3d11/device.c +++ b/dlls/d3d11/device.c @@ -7456,15 +7456,21 @@ static HRESULT STDMETHODCALLTYPE d3d11_video_device_CreateVideoProcessorEnumerat
static UINT STDMETHODCALLTYPE d3d11_video_device_GetVideoDecoderProfileCount(ID3D11VideoDevice1 *iface) { - FIXME("iface %p, stub!\n", iface); - return 0; + struct d3d_device *device = impl_from_ID3D11VideoDevice1(iface); + + TRACE("iface %p.\n", iface); + + return wined3d_device_get_video_decode_profile_count(device->wined3d_device); }
static HRESULT STDMETHODCALLTYPE d3d11_video_device_GetVideoDecoderProfile( ID3D11VideoDevice1 *iface, UINT index, GUID *profile) { - FIXME("iface %p, index %u, profile %p, stub!\n", iface, index, profile); - return E_NOTIMPL; + struct d3d_device *device = impl_from_ID3D11VideoDevice1(iface); + + TRACE("iface %p, index %u, profile %p.\n", iface, index, profile); + + return wined3d_device_get_video_decode_profile(device->wined3d_device, index, profile); }
static HRESULT STDMETHODCALLTYPE d3d11_video_device_CheckVideoDecoderFormat( diff --git a/dlls/wined3d/Makefile.in b/dlls/wined3d/Makefile.in index 128956c66be..19a36c25674 100644 --- a/dlls/wined3d/Makefile.in +++ b/dlls/wined3d/Makefile.in @@ -11,6 +11,7 @@ SOURCES = \ context_gl.c \ context_vk.c \ cs.c \ + decoder.c \ device.c \ directx.c \ ffp_gl.c \ diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index 0c90f67dcda..6f2e003b3ed 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -3693,6 +3693,7 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter_gl *adapter_gl, adapter->shader_backend = &glsl_shader_backend; adapter->vertex_pipe = &glsl_vertex_pipe; adapter->fragment_pipe = &glsl_fragment_pipe; + adapter->decoder_ops = &wined3d_null_decoder_ops;
if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT]) { diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 8dc944fafb6..1974535e52a 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -2528,6 +2528,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;
wined3d_adapter_vk_init_d3d_info(adapter_vk, wined3d_creation_flags);
diff --git a/dlls/wined3d/decoder.c b/dlls/wined3d/decoder.c new file mode 100644 index 00000000000..44f36e551da --- /dev/null +++ b/dlls/wined3d/decoder.c @@ -0,0 +1,29 @@ +/* + * Copyright 2024 Elizabeth Figura for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "wined3d_private.h" + +static void wined3d_null_decoder_get_profiles(struct wined3d_adapter *adapter, unsigned int *count, GUID *profiles) +{ + *count = 0; +} + +const struct wined3d_decoder_ops wined3d_null_decoder_ops = +{ + .get_profiles = wined3d_null_decoder_get_profiles, +}; diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 9c0a6344229..02836acb861 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -5636,3 +5636,30 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL else return CallWindowProcA(proc, window, message, wparam, lparam); } + +unsigned int CDECL wined3d_device_get_video_decode_profile_count(struct wined3d_device *device) +{ + GUID profiles[WINED3D_DECODER_MAX_PROFILE_COUNT]; + unsigned int count; + + TRACE("device %p.\n", device); + + device->adapter->decoder_ops->get_profiles(device->adapter, &count, profiles); + return count; +} + +HRESULT CDECL wined3d_device_get_video_decode_profile(struct wined3d_device *device, unsigned int idx, GUID *profile) +{ + GUID profiles[WINED3D_DECODER_MAX_PROFILE_COUNT]; + unsigned int count; + + TRACE("device %p, idx %u.\n", device, idx); + + device->adapter->decoder_ops->get_profiles(device->adapter, &count, profiles); + + if (idx >= count) + return E_INVALIDARG; + + *profile = profiles[idx]; + return S_OK; +} diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index dfe6b35ed0a..22c69b97410 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -3353,6 +3353,7 @@ static struct wined3d_adapter *wined3d_adapter_no3d_create(unsigned int ordinal, adapter->fragment_pipe = &none_fragment_pipe; adapter->misc_state_template = misc_state_template_no3d; adapter->shader_backend = &none_shader_backend; + adapter->decoder_ops = &wined3d_null_decoder_ops;
wined3d_adapter_no3d_init_d3d_info(adapter, wined3d_creation_flags);
diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index fa0dcd3ed39..e0b15c02b42 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -71,6 +71,8 @@ @ cdecl wined3d_device_get_state(ptr) @ cdecl wined3d_device_get_swapchain(ptr long) @ cdecl wined3d_device_get_swapchain_count(ptr) +@ cdecl wined3d_device_get_video_decode_profile_count(ptr) +@ cdecl wined3d_device_get_video_decode_profile(ptr long ptr) @ cdecl wined3d_device_get_wined3d(ptr) @ cdecl wined3d_device_incref(ptr) @ cdecl wined3d_device_process_vertices(ptr ptr long long long ptr ptr long long) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 50d4d958e24..6ef9ace1345 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -43,6 +43,7 @@ #include "wingdi.h" #include "winuser.h" #include "winternl.h" +#include "dxva.h" #include "ddk/d3dkmthk.h" #include "wine/debug.h"
@@ -2622,6 +2623,7 @@ struct wined3d_adapter const struct wined3d_fragment_pipe_ops *fragment_pipe; const struct wined3d_state_entry_template *misc_state_template; const struct wined3d_shader_backend_ops *shader_backend; + const struct wined3d_decoder_ops *decoder_ops; const struct wined3d_adapter_ops *adapter_ops; };
@@ -4459,6 +4461,15 @@ struct wined3d_palette uint32_t flags; };
+#define WINED3D_DECODER_MAX_PROFILE_COUNT 1 + +struct wined3d_decoder_ops +{ + void (*get_profiles)(struct wined3d_adapter *adapter, unsigned int *count, GUID *profiles); +}; + +extern const struct wined3d_decoder_ops wined3d_null_decoder_ops; + /* DirectDraw utility functions */ extern enum wined3d_format_id pixelformat_for_depth(DWORD depth);
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 85e12f8e621..1b2b37fdfd0 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2403,6 +2403,8 @@ struct wined3d_state * __cdecl wined3d_device_get_state(struct wined3d_device *d struct wined3d_swapchain * __cdecl wined3d_device_get_swapchain(const struct wined3d_device *device, UINT swapchain_idx); UINT __cdecl wined3d_device_get_swapchain_count(const struct wined3d_device *device); +unsigned int __cdecl wined3d_device_get_video_decode_profile_count(struct wined3d_device *device); +HRESULT __cdecl wined3d_device_get_video_decode_profile(struct wined3d_device *device, unsigned int idx, GUID *profile); struct wined3d * __cdecl wined3d_device_get_wined3d(const struct wined3d_device *device); ULONG __cdecl wined3d_device_incref(struct wined3d_device *device); HRESULT __cdecl wined3d_device_process_vertices(struct wined3d_device *device, struct wined3d_stateblock *stateblock,
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)
From: Elizabeth Figura zfigura@codeweavers.com
This patch is just boilerplate. --- dlls/d3d11/d3d11_private.h | 1 + dlls/d3d11/decoder.c | 53 +++++++++++++++++ dlls/wined3d/decoder.c | 105 +++++++++++++++++++++++++++++++++ dlls/wined3d/wined3d.spec | 3 + dlls/wined3d/wined3d_private.h | 3 + include/wine/wined3d.h | 13 ++++ 6 files changed, 178 insertions(+)
diff --git a/dlls/d3d11/d3d11_private.h b/dlls/d3d11/d3d11_private.h index 68745e3b815..910ad226269 100644 --- a/dlls/d3d11/d3d11_private.h +++ b/dlls/d3d11/d3d11_private.h @@ -623,6 +623,7 @@ struct d3d_video_decoder
struct wined3d_private_store private_store; struct d3d_device *device; + struct wined3d_decoder *wined3d_decoder; };
HRESULT d3d_video_decoder_create(struct d3d_device *device, const D3D11_VIDEO_DECODER_DESC *desc, diff --git a/dlls/d3d11/decoder.c b/dlls/d3d11/decoder.c index 5caf7b66c93..1e61dea0581 100644 --- a/dlls/d3d11/decoder.c +++ b/dlls/d3d11/decoder.c @@ -18,6 +18,8 @@ */
#include "d3d11_private.h" +#include "initguid.h" +#include "dxva.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d11);
@@ -65,6 +67,7 @@ static ULONG STDMETHODCALLTYPE d3d11_video_decoder_Release(ID3D11VideoDecoder *i
if (!refcount) { + wined3d_decoder_decref(decoder->wined3d_decoder); ID3D11Device2_Release(&decoder->device->ID3D11Device2_iface); wined3d_private_store_cleanup(&decoder->private_store); free(decoder); @@ -142,7 +145,32 @@ static const struct ID3D11VideoDecoderVtbl d3d11_video_decoder_vtbl = HRESULT d3d_video_decoder_create(struct d3d_device *device, const D3D11_VIDEO_DECODER_DESC *desc, const D3D11_VIDEO_DECODER_CONFIG *config, struct d3d_video_decoder **decoder) { + struct wined3d_decoder_desc wined3d_desc; struct d3d_video_decoder *object; + HRESULT hr; + + TRACE("profile %s, size %ux%u, output format %#x.\n", + debugstr_guid(&desc->Guid), desc->SampleWidth, desc->SampleHeight, desc->OutputFormat); + + TRACE(" guidConfigBitstreamEncryption: %s\n", debugstr_guid(&config->guidConfigBitstreamEncryption)); + TRACE(" guidConfigMBcontrolEncryption: %s\n", debugstr_guid(&config->guidConfigMBcontrolEncryption)); + TRACE(" guidConfigResidDiffEncryption: %s\n", debugstr_guid(&config->guidConfigResidDiffEncryption)); +#define X(field) TRACE(" " #field ": %u\n", config->field) + X(ConfigBitstreamRaw); + X(ConfigMBcontrolRasterOrder); + X(ConfigResidDiffHost); + X(ConfigSpatialResid8); + X(ConfigResid8Subtraction); + X(ConfigSpatialHost8or9Clipping); + X(ConfigSpatialResidInterleaved); + X(ConfigIntraResidUnsigned); + X(ConfigResidDiffAccelerator); + X(ConfigHostInverseScan); + X(ConfigSpecificIDCT); + X(Config4GroupedCoefs); + X(ConfigMinRenderTargetBuffCount); + X(ConfigDecoderSpecific); +#undef X
if (!(object = calloc(1, sizeof(*object)))) return E_OUTOFMEMORY; @@ -150,6 +178,31 @@ HRESULT d3d_video_decoder_create(struct d3d_device *device, const D3D11_VIDEO_DE object->ID3D11VideoDecoder_iface.lpVtbl = &d3d11_video_decoder_vtbl; object->refcount = 1;
+ wined3d_desc.codec = desc->Guid; + wined3d_desc.width = desc->SampleWidth; + wined3d_desc.height = desc->SampleHeight; + wined3d_desc.output_format = wined3dformat_from_dxgi_format(desc->OutputFormat); + wined3d_desc.long_slice_info = false; + + if (IsEqualGUID(&wined3d_desc.codec, &DXVA_ModeH264_VLD_NoFGT)) + { + if (config->ConfigBitstreamRaw == 1) + { + wined3d_desc.long_slice_info = true; + } + else if (config->ConfigBitstreamRaw != 2) + { + FIXME("Unsupported ConfigBitstreamRaw value %u.\n", config->ConfigBitstreamRaw); + return E_NOTIMPL; + } + } + + if (FAILED(hr = wined3d_decoder_create(device->wined3d_device, &wined3d_desc, &object->wined3d_decoder))) + { + free(object); + return hr; + } + wined3d_private_store_init(&object->private_store); object->device = device; ID3D11Device2_AddRef(&device->ID3D11Device2_iface); diff --git a/dlls/wined3d/decoder.c b/dlls/wined3d/decoder.c index 2da2f5c3c79..0752849eca2 100644 --- a/dlls/wined3d/decoder.c +++ b/dlls/wined3d/decoder.c @@ -21,6 +21,67 @@
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+struct wined3d_decoder +{ + LONG ref; + struct wined3d_device *device; + struct wined3d_decoder_desc desc; +}; + +ULONG CDECL wined3d_decoder_decref(struct wined3d_decoder *decoder) +{ + unsigned int refcount = InterlockedDecrement(&decoder->ref); + + TRACE("%p decreasing refcount to %u.\n", decoder, refcount); + + if (!refcount) + { + wined3d_mutex_lock(); + decoder->device->adapter->decoder_ops->destroy(decoder); + wined3d_mutex_unlock(); + } + + return refcount; +} + +static bool is_supported_codec(struct wined3d_adapter *adapter, const GUID *codec) +{ + GUID profiles[WINED3D_DECODER_MAX_PROFILE_COUNT]; + unsigned int count; + + adapter->decoder_ops->get_profiles(adapter, &count, profiles); + + for (unsigned int i = 0; i < count; ++i) + { + if (IsEqualGUID(&profiles[i], codec)) + return true; + } + return false; +} + +static void wined3d_decoder_init(struct wined3d_decoder *decoder, + struct wined3d_device *device, const struct wined3d_decoder_desc *desc) +{ + decoder->ref = 1; + decoder->device = device; + decoder->desc = *desc; +} + +HRESULT CDECL wined3d_decoder_create(struct wined3d_device *device, + const struct wined3d_decoder_desc *desc, struct wined3d_decoder **decoder) +{ + TRACE("device %p, codec %s, size %ux%u, output_format %s, decoder %p.\n", device, + debugstr_guid(&desc->codec), desc->width, desc->height, debug_d3dformat(desc->output_format), decoder); + + if (!is_supported_codec(device->adapter, &desc->codec)) + { + WARN("Codec %s is not supported; returning E_INVALIDARG.\n", debugstr_guid(&desc->codec)); + return E_INVALIDARG; + } + + return device->adapter->decoder_ops->create(device, desc, decoder); +} + static void wined3d_null_decoder_get_profiles(struct wined3d_adapter *adapter, unsigned int *count, GUID *profiles) { *count = 0; @@ -31,6 +92,16 @@ const struct wined3d_decoder_ops wined3d_null_decoder_ops = .get_profiles = wined3d_null_decoder_get_profiles, };
+struct wined3d_decoder_vk +{ + struct wined3d_decoder d; +}; + +static struct wined3d_decoder_vk *wined3d_decoder_vk(struct wined3d_decoder *decoder) +{ + return CONTAINING_RECORD(decoder, struct wined3d_decoder_vk, d); +} + 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; @@ -122,7 +193,41 @@ static void wined3d_decoder_vk_get_profiles(struct wined3d_adapter *adapter, uns } }
+static void wined3d_decoder_vk_destroy_object(void *object) +{ + struct wined3d_video_decoder_vk *decoder_vk = object; + + TRACE("decoder_vk %p.\n", decoder_vk); + + free(decoder_vk); +} + +static void wined3d_decoder_vk_destroy(struct wined3d_decoder *decoder) +{ + struct wined3d_decoder_vk *decoder_vk = wined3d_decoder_vk(decoder); + + wined3d_cs_destroy_object(decoder->device->cs, wined3d_decoder_vk_destroy_object, decoder_vk); +} + +static HRESULT wined3d_decoder_vk_create(struct wined3d_device *device, + const struct wined3d_decoder_desc *desc, struct wined3d_decoder **decoder) +{ + struct wined3d_decoder_vk *object; + + if (!(object = calloc(1, sizeof(*object)))) + return E_OUTOFMEMORY; + + wined3d_decoder_init(&object->d, device, desc); + + TRACE("Created decoder %p.\n", object); + *decoder = &object->d; + + return WINED3D_OK; +} + const struct wined3d_decoder_ops wined3d_decoder_vk_ops = { .get_profiles = wined3d_decoder_vk_get_profiles, + .create = wined3d_decoder_vk_create, + .destroy = wined3d_decoder_vk_destroy, }; diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index e0b15c02b42..6fdc2002ca3 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -40,6 +40,9 @@ @ cdecl wined3d_command_list_decref(ptr) @ cdecl wined3d_command_list_incref(ptr)
+@ cdecl wined3d_decoder_create(ptr ptr ptr) +@ cdecl wined3d_decoder_decref(ptr) + @ cdecl wined3d_deferred_context_create(ptr ptr) @ cdecl wined3d_deferred_context_destroy(ptr) @ cdecl wined3d_deferred_context_record_command_list(ptr long ptr) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 7b0f6469538..bf8f3f12d59 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4466,6 +4466,9 @@ struct wined3d_palette struct wined3d_decoder_ops { void (*get_profiles)(struct wined3d_adapter *adapter, unsigned int *count, GUID *profiles); + HRESULT (*create)(struct wined3d_device *device, + const struct wined3d_decoder_desc *desc, struct wined3d_decoder **decoder); + void (*destroy)(struct wined3d_decoder *decoder); };
extern const struct wined3d_decoder_ops wined3d_decoder_vk_ops; diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 1b2b37fdfd0..27e211a0b4e 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2050,6 +2050,14 @@ struct wined3d_blend_state_desc } rt[WINED3D_MAX_RENDER_TARGETS]; };
+struct wined3d_decoder_desc +{ + GUID codec; + unsigned int width, height; + enum wined3d_format_id output_format; + bool long_slice_info; +}; + struct wined3d_stencil_op_desc { enum wined3d_stencil_op fail_op; @@ -2223,6 +2231,7 @@ struct wined3d_adapter; struct wined3d_blend_state; struct wined3d_buffer; struct wined3d_command_list; +struct wined3d_decoder; struct wined3d_depth_stencil_state; struct wined3d_device; struct wined3d_device_context; @@ -2357,6 +2366,10 @@ ULONG __cdecl wined3d_buffer_incref(struct wined3d_buffer *buffer); ULONG __cdecl wined3d_command_list_decref(struct wined3d_command_list *list); ULONG __cdecl wined3d_command_list_incref(struct wined3d_command_list *list);
+HRESULT __cdecl wined3d_decoder_create(struct wined3d_device *device, + const struct wined3d_decoder_desc *desc, struct wined3d_decoder **decoder); +ULONG __cdecl wined3d_decoder_decref(struct wined3d_decoder *decoder); + HRESULT __cdecl wined3d_deferred_context_create(struct wined3d_device *device, struct wined3d_device_context **context); void __cdecl wined3d_deferred_context_destroy(struct wined3d_device_context *context); HRESULT __cdecl wined3d_deferred_context_record_command_list(struct wined3d_device_context *context,
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/wined3d/adapter_vk.c | 57 ++++++++++++++++++++++++--------------- dlls/wined3d/context_vk.c | 4 +-- dlls/wined3d/query.c | 4 +-- dlls/wined3d/swapchain.c | 6 ++--- dlls/wined3d/wined3d_vk.h | 10 ++++--- 5 files changed, 50 insertions(+), 31 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 311de30f052..4a9d49996c7 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -137,7 +137,7 @@ static void adapter_vk_destroy(struct wined3d_adapter *adapter) }
static HRESULT wined3d_select_vulkan_queue_family(const struct wined3d_adapter_vk *adapter_vk, - uint32_t *queue_family_index, uint32_t *timestamp_bits) + VkQueueFlags flags, struct wined3d_queue_vk *queue) { VkPhysicalDevice physical_device = adapter_vk->physical_device; const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info; @@ -153,17 +153,17 @@ static HRESULT wined3d_select_vulkan_queue_family(const struct wined3d_adapter_v
for (i = 0; i < count; ++i) { - if (queue_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) + if ((queue_properties[i].queueFlags & flags) == flags) { - *queue_family_index = i; - *timestamp_bits = queue_properties[i].timestampValidBits; + queue->vk_queue_family_index = i; + queue->timestamp_bits = queue_properties[i].timestampValidBits; free(queue_properties); return WINED3D_OK; } } free(queue_properties);
- WARN("Failed to find graphics queue.\n"); + WARN("Failed to find queue supporting %#x.\n", flags); return E_FAIL; }
@@ -361,39 +361,52 @@ static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wi const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info; struct wined3d_physical_device_info physical_device_info; static const float priorities[] = {1.0f}; + VkDeviceQueueCreateInfo queue_info[2]; struct wined3d_device_vk *device_vk; VkDevice vk_device = VK_NULL_HANDLE; - VkDeviceQueueCreateInfo queue_info; VkPhysicalDevice physical_device; VkDeviceCreateInfo device_info; - uint32_t queue_family_index; - uint32_t timestamp_bits; + HRESULT hr, decode_hr; VkResult vr; - HRESULT hr;
if (!(device_vk = calloc(1, sizeof(*device_vk)))) return E_OUTOFMEMORY;
- if (FAILED(hr = wined3d_select_vulkan_queue_family(adapter_vk, &queue_family_index, ×tamp_bits))) + if (FAILED(hr = wined3d_select_vulkan_queue_family(adapter_vk, + VK_QUEUE_GRAPHICS_BIT, &device_vk->graphics_queue))) goto fail;
+ decode_hr = wined3d_select_vulkan_queue_family(adapter_vk, + VK_QUEUE_VIDEO_DECODE_BIT_KHR, &device_vk->decode_queue); + physical_device = adapter_vk->physical_device;
get_physical_device_info(adapter_vk, &physical_device_info); wined3d_disable_vulkan_features(&physical_device_info);
- queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queue_info.pNext = NULL; - queue_info.flags = 0; - queue_info.queueFamilyIndex = queue_family_index; - queue_info.queueCount = ARRAY_SIZE(priorities); - queue_info.pQueuePriorities = priorities; + queue_info[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queue_info[0].pNext = NULL; + queue_info[0].flags = 0; + queue_info[0].queueFamilyIndex = device_vk->graphics_queue.vk_queue_family_index; + queue_info[0].queueCount = ARRAY_SIZE(priorities); + queue_info[0].pQueuePriorities = priorities; + device_info.queueCreateInfoCount = 1; + + if (decode_hr == S_OK) + { + queue_info[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queue_info[1].pNext = NULL; + queue_info[1].flags = 0; + queue_info[1].queueFamilyIndex = device_vk->decode_queue.vk_queue_family_index; + queue_info[1].queueCount = ARRAY_SIZE(priorities); + queue_info[1].pQueuePriorities = priorities; + ++device_info.queueCreateInfoCount; + }
device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; device_info.pNext = physical_device_info.features2.pNext; device_info.flags = 0; - device_info.queueCreateInfoCount = 1; - device_info.pQueueCreateInfos = &queue_info; + device_info.pQueueCreateInfos = queue_info; device_info.enabledLayerCount = 0; device_info.ppEnabledLayerNames = NULL; device_info.enabledExtensionCount = adapter_vk->device_extension_count; @@ -409,9 +422,11 @@ static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wi }
device_vk->vk_device = vk_device; - VK_CALL(vkGetDeviceQueue(vk_device, queue_family_index, 0, &device_vk->vk_queue)); - device_vk->vk_queue_family_index = queue_family_index; - device_vk->timestamp_bits = timestamp_bits; + VK_CALL(vkGetDeviceQueue(vk_device, device_vk->graphics_queue.vk_queue_family_index, + 0, &device_vk->graphics_queue.vk_queue)); + if (decode_hr == S_OK) + VK_CALL(vkGetDeviceQueue(vk_device, device_vk->decode_queue.vk_queue_family_index, + 0, &device_vk->decode_queue.vk_queue));
device_vk->vk_info = *vk_info; #define VK_DEVICE_PFN(name) \ diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index 9147a222b9d..edc77cd5f20 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -1965,7 +1965,7 @@ void wined3d_context_vk_submit_command_buffer(struct wined3d_context_vk *context submit_info.signalSemaphoreCount = signal_semaphore_count; submit_info.pSignalSemaphores = signal_semaphores;
- if ((vr = VK_CALL(vkQueueSubmit(device_vk->vk_queue, 1, &submit_info, buffer->vk_fence))) < 0) + if ((vr = VK_CALL(vkQueueSubmit(device_vk->graphics_queue.vk_queue, 1, &submit_info, buffer->vk_fence))) < 0) ERR("Failed to submit command buffer %p, vr %s.\n", buffer->vk_command_buffer, wined3d_debug_vkresult(vr));
@@ -4167,7 +4167,7 @@ HRESULT wined3d_context_vk_init(struct wined3d_context_vk *context_vk, struct wi command_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; command_pool_info.pNext = NULL; command_pool_info.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - command_pool_info.queueFamilyIndex = device_vk->vk_queue_family_index; + command_pool_info.queueFamilyIndex = device_vk->graphics_queue.vk_queue_family_index; if ((vr = VK_CALL(vkCreateCommandPool(device_vk->vk_device, &command_pool_info, NULL, &context_vk->vk_command_pool))) < 0) { diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c index a58ffbcf3d0..26e4f5e51f2 100644 --- a/dlls/wined3d/query.c +++ b/dlls/wined3d/query.c @@ -1915,7 +1915,7 @@ HRESULT wined3d_query_vk_create(struct wined3d_device *device, enum wined3d_quer break;
case WINED3D_QUERY_TYPE_TIMESTAMP: - if (!wined3d_device_vk(device)->timestamp_bits) + if (!wined3d_device_vk(device)->graphics_queue.timestamp_bits) { WARN("Timestamp queries not supported.\n"); return WINED3DERR_NOTAVAILABLE; @@ -1925,7 +1925,7 @@ HRESULT wined3d_query_vk_create(struct wined3d_device *device, enum wined3d_quer break;
case WINED3D_QUERY_TYPE_TIMESTAMP_DISJOINT: - if (!wined3d_device_vk(device)->timestamp_bits) + if (!wined3d_device_vk(device)->graphics_queue.timestamp_bits) { WARN("Timestamp queries not supported.\n"); return WINED3DERR_NOTAVAILABLE; diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index c8a624c9b8a..2811e588ecd 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -104,7 +104,7 @@ static void wined3d_swapchain_vk_destroy_vulkan_swapchain(struct wined3d_swapcha
vk_info = &wined3d_adapter_vk(device_vk->d.adapter)->vk_info;
- if ((vr = VK_CALL(vkQueueWaitIdle(device_vk->vk_queue))) < 0) + if ((vr = VK_CALL(vkQueueWaitIdle(device_vk->graphics_queue.vk_queue))) < 0) ERR("Failed to wait on queue, vr %s.\n", wined3d_debug_vkresult(vr)); free(swapchain_vk->vk_images); for (i = 0; i < swapchain_vk->image_count; ++i) @@ -898,7 +898,7 @@ static HRESULT wined3d_swapchain_vk_create_vulkan_swapchain(struct wined3d_swapc swapchain_vk->vk_surface = vk_surface;
if ((vr = VK_CALL(vkGetPhysicalDeviceSurfaceSupportKHR(adapter_vk->physical_device, - device_vk->vk_queue_family_index, vk_surface, &supported))) < 0 || !supported) + device_vk->graphics_queue.vk_queue_family_index, vk_surface, &supported))) < 0 || !supported) { ERR("Queue family does not support presentation on this surface, vr %s.\n", wined3d_debug_vkresult(vr)); goto fail; @@ -1160,7 +1160,7 @@ static VkResult wined3d_swapchain_vk_blit(struct wined3d_swapchain_vk *swapchain present_desc.pSwapchains = &swapchain_vk->vk_swapchain; present_desc.pImageIndices = &image_idx; present_desc.pResults = NULL; - if ((vr = VK_CALL(vkQueuePresentKHR(device_vk->vk_queue, &present_desc)))) + if ((vr = VK_CALL(vkQueuePresentKHR(device_vk->graphics_queue.vk_queue, &present_desc)))) WARN("Present returned vr %s.\n", wined3d_debug_vkresult(vr)); return vr; } diff --git a/dlls/wined3d/wined3d_vk.h b/dlls/wined3d/wined3d_vk.h index dd8a1bbfdb0..fd68c616c37 100644 --- a/dlls/wined3d/wined3d_vk.h +++ b/dlls/wined3d/wined3d_vk.h @@ -828,9 +828,13 @@ struct wined3d_device_vk struct wined3d_context_vk context_vk;
VkDevice vk_device; - VkQueue vk_queue; - uint32_t vk_queue_family_index; - uint32_t timestamp_bits; + + struct wined3d_queue_vk + { + VkQueue vk_queue; + uint32_t vk_queue_family_index; + int32_t timestamp_bits; + } graphics_queue, decode_queue;
struct wined3d_vk_info vk_info;
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/wined3d/context_vk.c | 34 ++++++++++++++++++++ dlls/wined3d/decoder.c | 67 ++++++++++++++++++++++++++++++++++++++- dlls/wined3d/wined3d_vk.h | 9 +++++- 3 files changed, 108 insertions(+), 2 deletions(-)
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index edc77cd5f20..f0a9b454f39 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -1089,6 +1089,35 @@ void wined3d_context_vk_destroy_vk_event(struct wined3d_context_vk *context_vk, o->command_buffer_id = command_buffer_id; }
+void wined3d_context_vk_destroy_vk_video_session(struct wined3d_context_vk *context_vk, + VkVideoSessionKHR vk_video_session, uint64_t command_buffer_id) +{ + struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); + const struct wined3d_vk_info *vk_info = context_vk->vk_info; + struct wined3d_retired_object_vk *o; + + /* The spec does not mention that the session may not be referenced by any + * active command buffers, but is probably an accidental omission. + * The proposal says "no longer used by any pending command buffers". */ + + if (context_vk->completed_command_buffer_id >= command_buffer_id) + { + VK_CALL(vkDestroyVideoSessionKHR(device_vk->vk_device, vk_video_session, NULL)); + TRACE("Destroyed video session 0x%s.\n", wine_dbgstr_longlong(vk_video_session)); + return; + } + + if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk))) + { + ERR("Leaking video session 0x%s.\n", wine_dbgstr_longlong(vk_video_session)); + return; + } + + o->type = WINED3D_RETIRED_VIDEO_SESSION_VK; + o->u.vk_video_session = vk_video_session; + o->command_buffer_id = command_buffer_id; +} + void wined3d_context_vk_destroy_image(struct wined3d_context_vk *context_vk, struct wined3d_image_vk *image) { wined3d_context_vk_destroy_vk_image(context_vk, image->vk_image, image->command_buffer_id); @@ -1277,6 +1306,11 @@ static void wined3d_context_vk_cleanup_resources(struct wined3d_context_vk *cont TRACE("Destroyed pipeline 0x%s.\n", wine_dbgstr_longlong(o->u.vk_pipeline)); break;
+ case WINED3D_RETIRED_VIDEO_SESSION_VK: + VK_CALL(vkDestroyVideoSessionKHR(device_vk->vk_device, o->u.vk_video_session, NULL)); + TRACE("Destroyed video session 0x%s.\n", wine_dbgstr_longlong(o->u.vk_video_session)); + break; + default: ERR("Unhandled object type %#x.\n", o->type); break; diff --git a/dlls/wined3d/decoder.c b/dlls/wined3d/decoder.c index 0752849eca2..bb43d61067b 100644 --- a/dlls/wined3d/decoder.c +++ b/dlls/wined3d/decoder.c @@ -95,6 +95,8 @@ const struct wined3d_decoder_ops wined3d_null_decoder_ops = struct wined3d_decoder_vk { struct wined3d_decoder d; + VkVideoSessionKHR vk_session; + uint64_t command_buffer_id; };
static struct wined3d_decoder_vk *wined3d_decoder_vk(struct wined3d_decoder *decoder) @@ -195,10 +197,15 @@ static void wined3d_decoder_vk_get_profiles(struct wined3d_adapter *adapter, uns
static void wined3d_decoder_vk_destroy_object(void *object) { - struct wined3d_video_decoder_vk *decoder_vk = object; + struct wined3d_decoder_vk *decoder_vk = object; + struct wined3d_context_vk *context_vk;
TRACE("decoder_vk %p.\n", decoder_vk);
+ context_vk = wined3d_context_vk(context_acquire(decoder_vk->d.device, NULL, 0)); + + wined3d_context_vk_destroy_vk_video_session(context_vk, decoder_vk->vk_session, decoder_vk->command_buffer_id); + free(decoder_vk); }
@@ -209,6 +216,62 @@ static void wined3d_decoder_vk_destroy(struct wined3d_decoder *decoder) wined3d_cs_destroy_object(decoder->device->cs, wined3d_decoder_vk_destroy_object, decoder_vk); }
+static void wined3d_decoder_vk_cs_init(void *object) +{ + VkVideoDecodeH264CapabilitiesKHR h264_caps = {.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_KHR}; + VkVideoDecodeCapabilitiesKHR decode_caps = {.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_CAPABILITIES_KHR}; + VkVideoSessionCreateInfoKHR session_desc = {.sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_CREATE_INFO_KHR}; + VkVideoProfileInfoKHR profile = {.sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR}; + VkVideoCapabilitiesKHR caps = {.sType = VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR}; + struct wined3d_decoder_vk *decoder_vk = object; + struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk(decoder_vk->d.device->adapter); + struct wined3d_device_vk *device_vk = wined3d_device_vk(decoder_vk->d.device); + const struct wined3d_vk_info *vk_info = &device_vk->vk_info; + const struct wined3d_format_vk *output_format; + VkResult vr; + + output_format = wined3d_format_vk(wined3d_get_format(&adapter_vk->a, decoder_vk->d.desc.output_format, 0)); + + session_desc.queueFamilyIndex = device_vk->decode_queue.vk_queue_family_index; + session_desc.pVideoProfile = &profile; + session_desc.pictureFormat = output_format->vk_format; + session_desc.referencePictureFormat = output_format->vk_format; + + fill_vk_profile_info(&profile, &decoder_vk->d.desc.codec, decoder_vk->d.desc.output_format); + + if (IsEqualGUID(&decoder_vk->d.desc.codec, &DXVA_ModeH264_VLD_NoFGT)) + { + caps.pNext = &decode_caps; + decode_caps.pNext = &h264_caps; + + vr = VK_CALL(vkGetPhysicalDeviceVideoCapabilitiesKHR(adapter_vk->physical_device, &profile, &caps)); + if (vr != VK_SUCCESS) + { + ERR("Device does not support the requested caps, vr %s.\n", wined3d_debug_vkresult(vr)); + return; + } + + session_desc.maxCodedExtent = caps.maxCodedExtent; + session_desc.maxDpbSlots = caps.maxDpbSlots; + session_desc.maxActiveReferencePictures = caps.maxActiveReferencePictures; + session_desc.pStdHeaderVersion = &caps.stdHeaderVersion; + } + else + { + ERR("Unsupported codec %s.\n", debugstr_guid(&decoder_vk->d.desc.codec)); + return; + } + + if ((vr = VK_CALL(vkCreateVideoSessionKHR(device_vk->vk_device, + &session_desc, NULL, &decoder_vk->vk_session)))) + { + ERR("Failed to create video session, vr %s.\n", wined3d_debug_vkresult(vr)); + return; + } + + TRACE("Created video session 0x%s.\n", wine_dbgstr_longlong(decoder_vk->vk_session)); +} + static HRESULT wined3d_decoder_vk_create(struct wined3d_device *device, const struct wined3d_decoder_desc *desc, struct wined3d_decoder **decoder) { @@ -219,6 +282,8 @@ static HRESULT wined3d_decoder_vk_create(struct wined3d_device *device,
wined3d_decoder_init(&object->d, device, desc);
+ wined3d_cs_init_object(device->cs, wined3d_decoder_vk_cs_init, object); + TRACE("Created decoder %p.\n", object); *decoder = &object->d;
diff --git a/dlls/wined3d/wined3d_vk.h b/dlls/wined3d/wined3d_vk.h index fd68c616c37..add8ec3cb3b 100644 --- a/dlls/wined3d/wined3d_vk.h +++ b/dlls/wined3d/wined3d_vk.h @@ -214,7 +214,10 @@ struct wined3d_device_vk; VK_DEVICE_PFN(vkCreateSwapchainKHR) \ VK_DEVICE_PFN(vkDestroySwapchainKHR) \ VK_DEVICE_PFN(vkGetSwapchainImagesKHR) \ - VK_DEVICE_PFN(vkQueuePresentKHR) + VK_DEVICE_PFN(vkQueuePresentKHR) \ + /* VK_KHR_video_queue */ \ + VK_DEVICE_EXT_PFN(vkCreateVideoSessionKHR) \ + VK_DEVICE_EXT_PFN(vkDestroyVideoSessionKHR)
#define DECLARE_VK_PFN(name) PFN_##name name;
@@ -444,6 +447,7 @@ enum wined3d_retired_object_type_vk WINED3D_RETIRED_QUERY_POOL_VK, WINED3D_RETIRED_EVENT_VK, WINED3D_RETIRED_PIPELINE_VK, + WINED3D_RETIRED_VIDEO_SESSION_VK, };
struct wined3d_retired_object_vk @@ -468,6 +472,7 @@ struct wined3d_retired_object_vk VkSampler vk_sampler; VkEvent vk_event; VkPipeline vk_pipeline; + VkVideoSessionKHR vk_video_session; struct { struct wined3d_query_pool_vk *pool_vk; @@ -706,6 +711,8 @@ void wined3d_context_vk_destroy_vk_event(struct wined3d_context_vk *context_vk, VkEvent vk_event, uint64_t command_buffer_id); void wined3d_context_vk_destroy_vk_pipeline(struct wined3d_context_vk *context_vk, VkPipeline vk_pipeline, uint64_t command_buffer_id); +void wined3d_context_vk_destroy_vk_video_session(struct wined3d_context_vk *context_vk, + VkPipeline vk_video_session, uint64_t command_buffer_id); void wined3d_context_vk_end_current_render_pass(struct wined3d_context_vk *context_vk); VkCommandBuffer wined3d_context_vk_get_command_buffer(struct wined3d_context_vk *context_vk); struct wined3d_pipeline_layout_vk *wined3d_context_vk_get_pipeline_layout(struct wined3d_context_vk *context_vk,
This merge request was approved by Jan Sikorski.