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 e704f85175b..7e12fd03e5a 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,