hwcontext_vulkan: only originate host image layout transitions from copyable layouts

Host image layout transitions may only originate from a layout in
pCopySrcLayouts, or from UNDEFINED, discarding the contents. The host
transfer path transitioned from whatever layout the frame was last
left in, which for pool-recycled frames can be a video layout, which
no driver lists as host-copyable.

Uploads overwrite the entire image, so transition from UNDEFINED
there. Downloads have to preserve the contents, so route frames in a
non-host-copyable layout through the GPU path.
This commit is contained in:
Lynne
2026-07-26 19:10:08 +08:00
parent 2dd3328240
commit ac16cfb86e

View File

@@ -4590,10 +4590,12 @@ static int vulkan_transfer_host(AVHWFramesContext *hwfc, AVFrame *hwf,
if (compat)
continue;
/* This should only ever happen on uploads, so using UNDEFINED is safe */
av_assert1(upload);
layout_ch_info[nb_layout_ch] = (VkHostImageLayoutTransitionInfoEXT) {
.sType = VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT,
.image = hwf_vk->img[i],
.oldLayout = hwf_vk->layout[i],
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
.subresourceRange = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
@@ -4715,8 +4717,27 @@ static int vulkan_transfer_frame(AVHWFramesContext *hwfc,
if (swf->width > hwfc->width || swf->height > hwfc->height)
return AVERROR(EINVAL);
if (hwctx->usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT &&
!(p->dprops.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY))
int host_copy = hwctx->usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT &&
!(p->dprops.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY);
/* Host layout transitions may only originate from a host-copyable layout */
if (!upload && host_copy) {
for (int i = 0; i < nb_images; i++) {
int compat = 0;
for (int j = 0; j < p->vkctx.host_image_props.copySrcLayoutCount; j++) {
if (hwf_vk->layout[i] == p->vkctx.host_image_props.pCopySrcLayouts[j]) {
compat = 1;
break;
}
}
if (!compat) {
host_copy = 0;
break;
}
}
}
if (host_copy)
return vulkan_transfer_host(hwfc, hwf, swf, upload);
for (int i = 0; i < av_pix_fmt_count_planes(swf->format); i++) {