History

hwcontext_vulkan: fix downloads; use the common host map function to map frame data

This commit uses the recently exported code for host mapping images back where it was exported from. The function also had broken download code for image downloading since its recent refactor.

Lynne committed 1 year ago

Commit 6c9affb1 parent a5b90ca1 file · +77 −160Browse files

Unified · Split

libavutil/hwcontext_vulkan.c+77−160
@@ -3957,7 +3957,7 @@ static int copy_buffer_data(AVHWFramesContext *hwfc, AVBufferRef *buf, · 3956 unmodified lines
3957 .size = VK_WHOLE_SIZE,3957 .size = VK_WHOLE_SIZE,
3958 };3958 };
3959 3959
3960 if (!(vkbuf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) && !upload) {3960 if (!upload && !(vkbuf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
3961 ret = vk->InvalidateMappedMemoryRanges(hwctx->act_dev, 1,3961 ret = vk->InvalidateMappedMemoryRanges(hwctx->act_dev, 1,
3962 &flush_info);3962 &flush_info);
3963 if (ret != VK_SUCCESS) {3963 if (ret != VK_SUCCESS) {
@@ -3967,15 +3967,25 @@ static int copy_buffer_data(AVHWFramesContext *hwfc, AVBufferRef *buf, · 3 unmodified lines
3967 }3967 }
3968 }3968 }
3969 3969
3970 for (int i = 0; i < planes; i++)3970 if (upload) {
3971 av_image_copy_plane(vkbuf->mapped_mem + region[i].bufferOffset,3971 for (int i = 0; i < planes; i++)
3972 region[i].bufferRowLength,3972 av_image_copy_plane(vkbuf->mapped_mem + region[i].bufferOffset,
3973 swf->data[i],3973 region[i].bufferRowLength,
3974 swf->linesize[i],3974 swf->data[i],
3975 swf->linesize[i],3975 swf->linesize[i],
3976 region[i].imageExtent.height);3976 swf->linesize[i],
3977 3977 region[i].imageExtent.height);
3978 if (!(vkbuf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) && upload) {3978 } else {
3979 for (int i = 0; i < planes; i++)
3980 av_image_copy_plane(swf->data[i],
3981 swf->linesize[i],
3982 vkbuf->mapped_mem + region[i].bufferOffset,
3983 region[i].bufferRowLength,
3984 swf->linesize[i],
3985 region[i].imageExtent.height);
3986 }
3987
3988 if (upload && !(vkbuf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
3979 ret = vk->FlushMappedMemoryRanges(hwctx->act_dev, 1,3989 ret = vk->FlushMappedMemoryRanges(hwctx->act_dev, 1,
3980 &flush_info);3990 &flush_info);
3981 if (ret != VK_SUCCESS) {3991 if (ret != VK_SUCCESS) {
@@ -3992,38 +4002,32 @@ static int get_plane_buf(AVHWFramesContext *hwfc, AVBufferRef **dst, · 10 unmodified lines
3992 AVFrame *swf, VkBufferImageCopy *region, int upload)4002 AVFrame *swf, VkBufferImageCopy *region, int upload)
3993{4003{
3994 int err;4004 int err;
4005 uint32_t p_w, p_h;
3995 VulkanFramesPriv *fp = hwfc->hwctx;4006 VulkanFramesPriv *fp = hwfc->hwctx;
3996 VulkanDevicePriv *p = hwfc->device_ctx->hwctx;4007 VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
3997 const int planes = av_pix_fmt_count_planes(swf->format);4008 const int planes = av_pix_fmt_count_planes(swf->format);
4009 VkBufferUsageFlags buf_usage = upload ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT :
4010 VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3998 4011
3999 size_t buf_offset = 0;4012 size_t buf_offset = 0;
4000 for (int i = 0; i < planes; i++) {4013 for (int i = 0; i < planes; i++) {
4001 size_t size;
4002 ptrdiff_t linesize = swf->linesize[i];
4003
4004 uint32_t p_w, p_h;
4005 get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i);4014 get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i);
4006 4015
4007 linesize = FFALIGN(linesize,
4008 p->props.properties.limits.optimalBufferCopyRowPitchAlignment);
4009 size = p_h*linesize;
4010
4011 region[i] = (VkBufferImageCopy) {4016 region[i] = (VkBufferImageCopy) {
4012 .bufferOffset = buf_offset,4017 .bufferOffset = buf_offset,
4013 .bufferRowLength = linesize,4018 .bufferRowLength = FFALIGN(swf->linesize[i],
4019 p->props.properties.limits.optimalBufferCopyRowPitchAlignment),
4014 .bufferImageHeight = p_h,4020 .bufferImageHeight = p_h,
4015 .imageSubresource.layerCount = 1,4021 .imageSubresource.layerCount = 1,
4016 .imageExtent = (VkExtent3D){ p_w, p_h, 1 },4022 .imageExtent = (VkExtent3D){ p_w, p_h, 1 },
4017 /* Rest of the fields adjusted/filled in later */4023 /* Rest of the fields adjusted/filled in later */
4018 };4024 };
4019 4025
4020 buf_offset = FFALIGN(buf_offset + size,4026 buf_offset += FFALIGN(p_h*region[i].bufferRowLength,
4021 p->props.properties.limits.optimalBufferCopyOffsetAlignment);4027 p->props.properties.limits.optimalBufferCopyOffsetAlignment);
4022 }4028 }
4023 4029
4024 err = ff_vk_get_pooled_buffer(&p->vkctx, &fp->tmp, dst,4030 err = ff_vk_get_pooled_buffer(&p->vkctx, &fp->tmp, dst, buf_usage,
4025 VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
4026 VK_BUFFER_USAGE_TRANSFER_DST_BIT,
4027 NULL, buf_offset,4031 NULL, buf_offset,
4028 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |4032 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
4029 VK_MEMORY_PROPERTY_HOST_CACHED_BIT);4033 VK_MEMORY_PROPERTY_HOST_CACHED_BIT);
@@ -4033,155 +4037,53 @@ static int get_plane_buf(AVHWFramesContext *hwfc, AVBufferRef **dst, · 3 unmodified lines
4033 return 0;4037 return 0;
4034}4038}
4035 4039
4036static int create_mapped_buffer(AVHWFramesContext *hwfc,
4037 FFVkBuffer *vkb, VkBufferUsageFlags usage,
4038 size_t size,
4039 VkExternalMemoryBufferCreateInfo *create_desc,
4040 VkImportMemoryHostPointerInfoEXT *import_desc,
4041 VkMemoryHostPointerPropertiesEXT props)
4042{
4043 int err;
4044 VkResult ret;
4045 VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
4046 FFVulkanFunctions *vk = &p->vkctx.vkfn;
4047 AVVulkanDeviceContext *hwctx = &p->p;
4048
4049 VkBufferCreateInfo buf_spawn = {
4050 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
4051 .pNext = create_desc,
4052 .usage = usage,
4053 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
4054 .size = size,
4055 };
4056 VkMemoryRequirements req = {
4057 .size = size,
4058 .alignment = p->hprops.minImportedHostPointerAlignment,
4059 .memoryTypeBits = props.memoryTypeBits,
4060 };
4061
4062 err = ff_vk_alloc_mem(&p->vkctx, &req,
4063 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
4064 import_desc, &vkb->flags, &vkb->mem);
4065 if (err < 0)
4066 return err;
4067
4068 ret = vk->CreateBuffer(hwctx->act_dev, &buf_spawn, hwctx->alloc, &vkb->buf);
4069 if (ret != VK_SUCCESS) {
4070 vk->FreeMemory(hwctx->act_dev, vkb->mem, hwctx->alloc);
4071 return AVERROR_EXTERNAL;
4072 }
4073
4074 ret = vk->BindBufferMemory(hwctx->act_dev, vkb->buf, vkb->mem, 0);
4075 if (ret != VK_SUCCESS) {
4076 vk->FreeMemory(hwctx->act_dev, vkb->mem, hwctx->alloc);
4077 vk->DestroyBuffer(hwctx->act_dev, vkb->buf, hwctx->alloc);
4078 return AVERROR_EXTERNAL;
4079 }
4080
4081 return 0;
4082}
4083
4084static void destroy_avvkbuf(void *opaque, uint8_t *data)
4085{
4086 FFVulkanContext *s = opaque;
4087 FFVkBuffer *buf = (FFVkBuffer *)data;
4088 ff_vk_free_buf(s, buf);
4089 av_free(buf);
4090}
4091
4092static int host_map_frame(AVHWFramesContext *hwfc, AVBufferRef **dst, int *nb_bufs,4040static int host_map_frame(AVHWFramesContext *hwfc, AVBufferRef **dst, int *nb_bufs,
4093 AVFrame *swf, VkBufferImageCopy *region, int upload)4041 AVFrame *swf, VkBufferImageCopy *region, int upload)
4094{4042{
4095 int err;4043 int err;
4096 VkResult ret;
4097 VulkanDevicePriv *p = hwfc->device_ctx->hwctx;4044 VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
4098 FFVulkanFunctions *vk = &p->vkctx.vkfn;
4099 AVVulkanDeviceContext *hwctx = &p->p;
4100 4045
4046 int nb_src_bufs;
4101 const int planes = av_pix_fmt_count_planes(swf->format);4047 const int planes = av_pix_fmt_count_planes(swf->format);
4048 VkBufferUsageFlags buf_usage = upload ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT :
4049 VK_BUFFER_USAGE_TRANSFER_DST_BIT;
4102 4050
4103 VkExternalMemoryBufferCreateInfo create_desc = {4051 /* We can't host map images with negative strides */
4104 .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,4052 for (int i = 0; i < planes; i++)
4105 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,4053 if (swf->linesize[i] < 0)
4106 };4054 return AVERROR(EINVAL);
4107 VkImportMemoryHostPointerInfoEXT import_desc = {
4108 .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT,
4109 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,
4110 };
4111 VkMemoryHostPointerPropertiesEXT props;
4112
4113 for (int i = 0; i < planes; i++) {
4114 FFVkBuffer *vkb;
4115 uint32_t p_w, p_h;
4116 size_t offs;
4117 size_t buffer_size;
4118
4119 /* We can't host map images with negative strides */
4120 if (swf->linesize[i] < 0) {
4121 err = AVERROR(EINVAL);
4122 goto fail;
4123 }
4124
4125 get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i);
4126
4127 /* Get the previous point at which mapping was possible and use it */
4128 offs = (uintptr_t)swf->data[i] % p->hprops.minImportedHostPointerAlignment;
4129 import_desc.pHostPointer = swf->data[i] - offs;
4130
4131 props = (VkMemoryHostPointerPropertiesEXT) {
4132 VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT,
4133 };
4134 ret = vk->GetMemoryHostPointerPropertiesEXT(hwctx->act_dev,
4135 import_desc.handleType,
4136 import_desc.pHostPointer,
4137 &props);
4138 if (!(ret == VK_SUCCESS && props.memoryTypeBits)) {
4139 err = AVERROR(EINVAL);
4140 goto fail;
4141 }
4142
4143 /* Buffer region for this plane */
4144 region[i] = (VkBufferImageCopy) {
4145 .bufferOffset = offs,
4146 .bufferRowLength = swf->linesize[i],
4147 .bufferImageHeight = p_h,
4148 .imageSubresource.layerCount = 1,
4149 .imageExtent = (VkExtent3D){ p_w, p_h, 1 },
4150 /* Rest of the fields adjusted/filled in later */
4151 };
4152 4055
4153 /* Add the offset at the start, which gets ignored */4056 /* Count the number of buffers in the software frame */
4154 buffer_size = offs + swf->linesize[i]*p_h;4057 nb_src_bufs = 0;
4155 buffer_size = FFALIGN(buffer_size, p->props.properties.limits.minMemoryMapAlignment);4058 while (swf->buf[nb_src_bufs])
4156 buffer_size = FFALIGN(buffer_size, p->hprops.minImportedHostPointerAlignment);4059 nb_src_bufs++;
4157 4060
4158 /* Create a buffer */4061 /* Single buffer contains all planes */
4159 vkb = av_mallocz(sizeof(*vkb));4062 if (nb_src_bufs == 1) {
4160 if (!vkb) {4063 err = ff_vk_host_map_buffer(&p->vkctx, &dst[0],
4161 err = AVERROR(ENOMEM);4064 swf->data[0], swf->buf[0],
4162 goto fail;4065 buf_usage);
4163 }4066 if (err < 0)
4067 return err;
4068 (*nb_bufs)++;
4164 4069
4165 err = create_mapped_buffer(hwfc, vkb,4070 for (int i = 0; i < planes; i++)
4166 upload ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT :4071 region[i].bufferOffset = ((FFVkBuffer *)dst[0]->data)->virtual_offset +
4167 VK_BUFFER_USAGE_TRANSFER_DST_BIT,4072 swf->data[i] - swf->data[0];
4168 buffer_size, &create_desc, &import_desc,4073 } else if (nb_src_bufs == planes) { /* One buffer per plane */
4169 props);4074 for (int i = 0; i < planes; i++) {
4170 if (err < 0) {4075 err = ff_vk_host_map_buffer(&p->vkctx, &dst[i],
4171 av_free(vkb);4076 swf->data[i], swf->buf[i],
4172 goto fail;4077 buf_usage);
4173 }4078 if (err < 0)
4079 goto fail;
4080 (*nb_bufs)++;
4174 4081
4175 /* Create a ref */4082 region[i].bufferOffset = ((FFVkBuffer *)dst[i]->data)->virtual_offset;
4176 dst[*nb_bufs] = av_buffer_create((uint8_t *)vkb, sizeof(*vkb),
4177 destroy_avvkbuf, &p->vkctx, 0);
4178 if (!dst[*nb_bufs]) {
4179 destroy_avvkbuf(&p->vkctx, (uint8_t *)vkb);
4180 err = AVERROR(ENOMEM);
4181 goto fail;
4182 }4083 }
4183 4084 } else {
4184 (*nb_bufs)++;4085 /* Weird layout (3 planes, 2 buffers), patch welcome, fallback to copy */
4086 return AVERROR_PATCHWELCOME;
4185 }4087 }
4186 4088
4187 return 0;4089 return 0;
@@ -4228,6 +4130,21 @@ static int vulkan_transfer_frame(AVHWFramesContext *hwfc, · 40 unmodified lines
4228 if (swf->width > hwfc->width || swf->height > hwfc->height)4130 if (swf->width > hwfc->width || swf->height > hwfc->height)
4229 return AVERROR(EINVAL);4131 return AVERROR(EINVAL);
4230 4132
4133 for (int i = 0; i < av_pix_fmt_count_planes(swf->format); i++) {
4134 uint32_t p_w, p_h;
4135 get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i);
4136
4137 /* Buffer region for this plane */
4138 region[i] = (VkBufferImageCopy) {
4139 .bufferOffset = 0,
4140 .bufferRowLength = swf->linesize[i],
4141 .bufferImageHeight = p_h,
4142 .imageSubresource.layerCount = 1,
4143 .imageExtent = (VkExtent3D){ p_w, p_h, 1 },
4144 /* Rest of the fields adjusted/filled in later */
4145 };
4146 }
4147
4231 /* Setup buffers first */4148 /* Setup buffers first */
4232 if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY) {4149 if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY) {
4233 err = host_map_frame(hwfc, bufs, &nb_bufs, swf, region, upload);4150 err = host_map_frame(hwfc, bufs, &nb_bufs, swf, region, upload);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t