| @@ -80,6 +80,7 @@ typedef struct VulkanDeviceFeatures { · 79 unmodified lines |
| 80 | 80 | VkPhysicalDeviceVulkan13Features vulkan_1_3; |
| 81 | 81 | VkPhysicalDeviceTimelineSemaphoreFeatures timeline_semaphore; |
| 82 | 82 | VkPhysicalDeviceShaderSubgroupRotateFeaturesKHR subgroup_rotate; |
| 83 | + VkPhysicalDeviceHostImageCopyFeaturesEXT host_image_copy; |
| 83 | 84 | |
| 84 | 85 | #ifdef VK_KHR_shader_expect_assume |
| 85 | 86 | VkPhysicalDeviceShaderExpectAssumeFeaturesKHR expect_assume; |
| @@ -209,6 +210,8 @@ static void device_features_init(AVHWDeviceContext *ctx, VulkanDeviceFeatures *f · 123 unmodified lines |
| 209 | 210 | VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES); |
| 210 | 211 | FF_VK_STRUCT_EXT(s, &feats->device, &feats->subgroup_rotate, FF_VK_EXT_SUBGROUP_ROTATE, |
| 211 | 212 | VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_ROTATE_FEATURES_KHR); |
| 213 | + FF_VK_STRUCT_EXT(s, &feats->device, &feats->host_image_copy, FF_VK_EXT_HOST_IMAGE_COPY, |
| 214 | + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES_EXT); |
| 212 | 215 | |
| 213 | 216 | #ifdef VK_KHR_shader_expect_assume |
| 214 | 217 | FF_VK_STRUCT_EXT(s, &feats->device, &feats->expect_assume, FF_VK_EXT_EXPECT_ASSUME, |
| @@ -285,6 +288,7 @@ static void device_features_copy_needed(VulkanDeviceFeatures *dst, VulkanDeviceF · 70 unmodified lines |
| 285 | 288 | |
| 286 | 289 | COPY_VAL(timeline_semaphore.timelineSemaphore); |
| 287 | 290 | COPY_VAL(subgroup_rotate.shaderSubgroupRotate); |
| 291 | + COPY_VAL(host_image_copy.hostImageCopy); |
| 288 | 292 | |
| 289 | 293 | COPY_VAL(video_maintenance_1.videoMaintenance1); |
| 290 | 294 | #ifdef VK_KHR_video_maintenance2 |
| @@ -606,6 +610,7 @@ static const VulkanOptExtension optional_device_exts[] = { · 315 unmodified lines |
| 606 | 610 | { VK_KHR_COOPERATIVE_MATRIX_EXTENSION_NAME, FF_VK_EXT_COOP_MATRIX }, |
| 607 | 611 | { VK_EXT_SHADER_OBJECT_EXTENSION_NAME, FF_VK_EXT_SHADER_OBJECT }, |
| 608 | 612 | { VK_KHR_SHADER_SUBGROUP_ROTATE_EXTENSION_NAME, FF_VK_EXT_SUBGROUP_ROTATE }, |
| 613 | + { VK_EXT_HOST_IMAGE_COPY_EXTENSION_NAME, FF_VK_EXT_HOST_IMAGE_COPY }, |
| 609 | 614 | #ifdef VK_KHR_shader_expect_assume |
| 610 | 615 | { VK_KHR_SHADER_EXPECT_ASSUME_EXTENSION_NAME, FF_VK_EXT_EXPECT_ASSUME }, |
| 611 | 616 | #endif |
| @@ -2825,11 +2830,15 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc) · 2213 unmodified lines |
| 2825 | 2830 | |
| 2826 | 2831 | /* Image usage flags */ |
| 2827 | 2832 | if (!hwctx->usage) { |
| 2828 | | − hwctx->usage = supported_usage & (VK_IMAGE_USAGE_TRANSFER_DST_BIT | |
| 2829 | | − VK_IMAGE_USAGE_TRANSFER_SRC_BIT | |
| 2833 | + hwctx->usage = supported_usage & (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | |
| 2830 | 2834 | VK_IMAGE_USAGE_STORAGE_BIT | |
| 2831 | 2835 | VK_IMAGE_USAGE_SAMPLED_BIT); |
| 2832 | 2836 | |
| 2837 | + if (p->vkctx.extensions & FF_VK_EXT_HOST_IMAGE_COPY) |
| 2838 | + hwctx->usage |= supported_usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT; |
| 2839 | + else |
| 2840 | + hwctx->usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| 2841 | + |
| 2833 | 2842 | /* Enables encoding of images, if supported by format and extensions */ |
| 2834 | 2843 | if ((supported_usage & VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR) && |
| 2835 | 2844 | (p->vkctx.extensions & (FF_VK_EXT_VIDEO_ENCODE_QUEUE | |
| @@ -4148,6 +4157,113 @@ fail: · 1312 unmodified lines |
| 4148 | 4157 | return err; |
| 4149 | 4158 | } |
| 4150 | 4159 | |
| 4160 | +static int vulkan_transfer_host(AVHWFramesContext *hwfc, AVFrame *hwf, |
| 4161 | + AVFrame *swf, int upload) |
| 4162 | +{ |
| 4163 | + VulkanDevicePriv *p = hwfc->device_ctx->hwctx; |
| 4164 | + AVVulkanFramesContext *hwfc_vk = hwfc->hwctx; |
| 4165 | + AVVulkanDeviceContext *hwctx = &p->p; |
| 4166 | + FFVulkanFunctions *vk = &p->vkctx.vkfn; |
| 4167 | + |
| 4168 | + AVVkFrame *hwf_vk = (AVVkFrame *)hwf->data[0]; |
| 4169 | + const int planes = av_pix_fmt_count_planes(swf->format); |
| 4170 | + const int nb_images = ff_vk_count_images(hwf_vk); |
| 4171 | + |
| 4172 | + VkSemaphoreWaitInfo sem_wait; |
| 4173 | + VkHostImageLayoutTransitionInfo layout_ch_info[]; |
| 4174 | + int nb_layout_ch = 0; |
| 4175 | + |
| 4176 | + hwfc_vk->lock_frame(hwfc, hwf_vk); |
| 4177 | + |
| 4178 | + for (int i = 0; i < nb_images; i++) { |
| 4179 | + if (hwf_vk->layout[i]) |
| 4180 | + continue; |
| 4181 | + |
| 4182 | + layout_ch_info[nb_layout_ch++] = (VkHostImageLayoutTransitionInfo) { |
| 4183 | + .sType = VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO, |
| 4184 | + .image = hwf_vk->img[i], |
| 4185 | + .oldLayout = hwf_vk->layout[i], |
| 4186 | + .newLayout = VK_IMAGE_LAYOUT_GENERAL, |
| 4187 | + .subresourceRange = { |
| 4188 | + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, |
| 4189 | + .levelCount = 1, |
| 4190 | + .layerCount = 1, |
| 4191 | + }; |
| 4192 | + }; |
| 4193 | + } |
| 4194 | + |
| 4195 | + if (nb_layout_ch) |
| 4196 | + vk->TransitionImageLayoutEXT(hwctx->act_dev, |
| 4197 | + nb_layout_ch, layout_ch_info); |
| 4198 | + |
| 4199 | + sem_wait = (VkSemaphoreWaitInfo) { |
| 4200 | + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, |
| 4201 | + .pSemaphores = hwf_vk->sem, |
| 4202 | + .pValues = hwf_vk->sem_value, |
| 4203 | + .semaphoreCount = nb_images, |
| 4204 | + }; |
| 4205 | + |
| 4206 | + vk->WaitSemaphores(hwctx->act_dev, &sem_wait, UINT64_MAX); |
| 4207 | + |
| 4208 | + if (upload) { |
| 4209 | + VkMemoryToImageCopy region_info = { |
| 4210 | + .sType = VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY, |
| 4211 | + .imageSubresource = { |
| 4212 | + .layerCount = 1, |
| 4213 | + }, |
| 4214 | + }; |
| 4215 | + VkCopyMemoryToImageInfo copy_info = { |
| 4216 | + .sType = VK_STRUCTURE_TYPE_COPY_MEMORY_TO_IMAGE_INFO, |
| 4217 | + .flags = VK_HOST_IMAGE_COPY_MEMCPY, |
| 4218 | + .regionCount = 1, |
| 4219 | + .pRegions = ®ion_info, |
| 4220 | + }; |
| 4221 | + for (int i = 0; i < planes; i++) { |
| 4222 | + int img_idx = FFMIN(i, (nb_images - 1)); |
| 4223 | + uint32_t p_w, p_h; |
| 4224 | + get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i); |
| 4225 | + |
| 4226 | + region_info.pHostPointer = swf->data[i]; |
| 4227 | + region_info.imageSubresource.aspectMask = ff_vk_aspect_flag(hwf, i); |
| 4228 | + region_info.imageExtent = (VkExtent3D){ p_w, p_h, 1 }; |
| 4229 | + copy_info.dstImage = hwf_vk->img[img_idx]; |
| 4230 | + copy_info.dstImageLayout = hwf_vk->layout[img_idx]; |
| 4231 | + |
| 4232 | + vk->CopyMemoryToImageEXT(hwctx->act_dev, ©_info); |
| 4233 | + } |
| 4234 | + } else { |
| 4235 | + VkImageToMemoryCopy region_info = { |
| 4236 | + .sType = VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY, |
| 4237 | + .imageSubresource = { |
| 4238 | + .layerCount = 1, |
| 4239 | + }, |
| 4240 | + }; |
| 4241 | + VkCopyImageToMemoryInfo copy_info = { |
| 4242 | + .sType = VK_STRUCTURE_TYPE_COPY_IMAGE_TO_MEMORY_INFO, |
| 4243 | + .flags = VK_HOST_IMAGE_COPY_MEMCPY, |
| 4244 | + .regionCount = 1, |
| 4245 | + .pRegions = ®ion_info, |
| 4246 | + }; |
| 4247 | + for (int i = 0; i < planes; i++) { |
| 4248 | + int img_idx = FFMIN(i, (nb_images - 1)); |
| 4249 | + uint32_t p_w, p_h; |
| 4250 | + get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i); |
| 4251 | + |
| 4252 | + region_info.pHostPointer = swf->data[i]; |
| 4253 | + region_info.imageSubresource.aspectMask = ff_vk_aspect_flag(hwf, i); |
| 4254 | + region_info.imageExtent = (VkExtent3D){ p_w, p_h, 1 }; |
| 4255 | + copy_info.srcImage = hwf_vk->img[img_idx]; |
| 4256 | + copy_info.srcImageLayout = hwf_vk->layout[img_idx]; |
| 4257 | + |
| 4258 | + vk->CopyImageToMemoryEXT(hwctx->act_dev, ©_info); |
| 4259 | + } |
| 4260 | + } |
| 4261 | + |
| 4262 | + hwfc_vk->unlock_frame(hwfc, hwf_vk); |
| 4263 | + |
| 4264 | + return 0; |
| 4265 | +} |
| 4266 | + |
| 4151 | 4267 | static int vulkan_transfer_frame(AVHWFramesContext *hwfc, |
| 4152 | 4268 | AVFrame *swf, AVFrame *hwf, |
| 4153 | 4269 | int upload) |
| @@ -4184,6 +4300,9 @@ static int vulkan_transfer_frame(AVHWFramesContext *hwfc, · 30 unmodified lines |
| 4184 | 4300 | if (swf->width > hwfc->width || swf->height > hwfc->height) |
| 4185 | 4301 | return AVERROR(EINVAL); |
| 4186 | 4302 | |
| 4303 | + if (p->vkctx.extensions & FF_VK_EXT_HOST_IMAGE_COPY) |
| 4304 | + return vulkan_transfer_host(hwfc, hwf, swf, upload); |
| 4305 | + |
| 4187 | 4306 | for (int i = 0; i < av_pix_fmt_count_planes(swf->format); i++) { |
| 4188 | 4307 | uint32_t p_w, p_h; |
| 4189 | 4308 | get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i); |