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
39573957 .size = VK_WHOLE_SIZE,
39583958 };
39593959
3960− if (!(vkbuf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) && !upload) {
3960+ if (!upload && !(vkbuf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
39613961 ret = vk->InvalidateMappedMemoryRanges(hwctx->act_dev, 1,
39623962 &flush_info);
39633963 if (ret != VK_SUCCESS) {
@@ -3967,15 +3967,25 @@ static int copy_buffer_data(AVHWFramesContext *hwfc, AVBufferRef *buf, · 3 unmodified lines
39673967 }
39683968 }
39693969
3970− for (int i = 0; i < planes; i++)
3971− av_image_copy_plane(vkbuf->mapped_mem + region[i].bufferOffset,
3972− region[i].bufferRowLength,
3973− swf->data[i],
3974− swf->linesize[i],
3975− swf->linesize[i],
3976− region[i].imageExtent.height);
3977−
3978− if (!(vkbuf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) && upload) {
3970+ if (upload) {
3971+ for (int i = 0; i < planes; i++)
3972+ av_image_copy_plane(vkbuf->mapped_mem + region[i].bufferOffset,
3973+ region[i].bufferRowLength,
3974+ swf->data[i],
3975+ swf->linesize[i],
3976+ swf->linesize[i],
3977+ region[i].imageExtent.height);
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)) {
39793989 ret = vk->FlushMappedMemoryRanges(hwctx->act_dev, 1,
39803990 &flush_info);
39813991 if (ret != VK_SUCCESS) {
@@ -3992,38 +4002,32 @@ static int get_plane_buf(AVHWFramesContext *hwfc, AVBufferRef **dst, · 10 unmodified lines
39924002 AVFrame *swf, VkBufferImageCopy *region, int upload)
39934003 {
39944004 int err;
4005+ uint32_t p_w, p_h;
39954006 VulkanFramesPriv *fp = hwfc->hwctx;
39964007 VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
39974008 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;
39984011
39994012 size_t buf_offset = 0;
40004013 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;
40054014 get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i);
40064015
4007− linesize = FFALIGN(linesize,
4008− p->props.properties.limits.optimalBufferCopyRowPitchAlignment);
4009− size = p_h*linesize;
4010−
40114016 region[i] = (VkBufferImageCopy) {
40124017 .bufferOffset = buf_offset,
4013− .bufferRowLength = linesize,
4018+ .bufferRowLength = FFALIGN(swf->linesize[i],
4019+ p->props.properties.limits.optimalBufferCopyRowPitchAlignment),
40144020 .bufferImageHeight = p_h,
40154021 .imageSubresource.layerCount = 1,
40164022 .imageExtent = (VkExtent3D){ p_w, p_h, 1 },
40174023 /* Rest of the fields adjusted/filled in later */
40184024 };
40194025
4020− buf_offset = FFALIGN(buf_offset + size,
4021− p->props.properties.limits.optimalBufferCopyOffsetAlignment);
4026+ buf_offset += FFALIGN(p_h*region[i].bufferRowLength,
4027+ p->props.properties.limits.optimalBufferCopyOffsetAlignment);
40224028 }
40234029
4024− err = ff_vk_get_pooled_buffer(&p->vkctx, &fp->tmp, dst,
4025− VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
4026− VK_BUFFER_USAGE_TRANSFER_DST_BIT,
4030+ err = ff_vk_get_pooled_buffer(&p->vkctx, &fp->tmp, dst, buf_usage,
40274031 NULL, buf_offset,
40284032 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
40294033 VK_MEMORY_PROPERTY_HOST_CACHED_BIT);
@@ -4033,155 +4037,53 @@ static int get_plane_buf(AVHWFramesContext *hwfc, AVBufferRef **dst, · 3 unmodified lines
40334037 return 0;
40344038 }
40354039
4036−static 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−
4084−static 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−
40924040 static int host_map_frame(AVHWFramesContext *hwfc, AVBufferRef **dst, int *nb_bufs,
40934041 AVFrame *swf, VkBufferImageCopy *region, int upload)
40944042 {
40954043 int err;
4096− VkResult ret;
40974044 VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
4098− FFVulkanFunctions *vk = &p->vkctx.vkfn;
4099− AVVulkanDeviceContext *hwctx = &p->p;
41004045
4046+ int nb_src_bufs;
41014047 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;
41024050
4103− VkExternalMemoryBufferCreateInfo create_desc = {
4104− .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
4105− .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,
4106− };
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− };
4051+ /* We can't host map images with negative strides */
4052+ for (int i = 0; i < planes; i++)
4053+ if (swf->linesize[i] < 0)
4054+ return AVERROR(EINVAL);
41524055
4153− /* Add the offset at the start, which gets ignored */
4154− buffer_size = offs + swf->linesize[i]*p_h;
4155− buffer_size = FFALIGN(buffer_size, p->props.properties.limits.minMemoryMapAlignment);
4156− buffer_size = FFALIGN(buffer_size, p->hprops.minImportedHostPointerAlignment);
4056+ /* Count the number of buffers in the software frame */
4057+ nb_src_bufs = 0;
4058+ while (swf->buf[nb_src_bufs])
4059+ nb_src_bufs++;
41574060
4158− /* Create a buffer */
4159− vkb = av_mallocz(sizeof(*vkb));
4160− if (!vkb) {
4161− err = AVERROR(ENOMEM);
4162− goto fail;
4163− }
4061+ /* Single buffer contains all planes */
4062+ if (nb_src_bufs == 1) {
4063+ err = ff_vk_host_map_buffer(&p->vkctx, &dst[0],
4064+ swf->data[0], swf->buf[0],
4065+ buf_usage);
4066+ if (err < 0)
4067+ return err;
4068+ (*nb_bufs)++;
41644069
4165− err = create_mapped_buffer(hwfc, vkb,
4166− upload ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT :
4167− VK_BUFFER_USAGE_TRANSFER_DST_BIT,
4168− buffer_size, &create_desc, &import_desc,
4169− props);
4170− if (err < 0) {
4171− av_free(vkb);
4172− goto fail;
4173− }
4070+ for (int i = 0; i < planes; i++)
4071+ region[i].bufferOffset = ((FFVkBuffer *)dst[0]->data)->virtual_offset +
4072+ swf->data[i] - swf->data[0];
4073+ } else if (nb_src_bufs == planes) { /* One buffer per plane */
4074+ for (int i = 0; i < planes; i++) {
4075+ err = ff_vk_host_map_buffer(&p->vkctx, &dst[i],
4076+ swf->data[i], swf->buf[i],
4077+ buf_usage);
4078+ if (err < 0)
4079+ goto fail;
4080+ (*nb_bufs)++;
41744081
4175− /* Create a ref */
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;
4082+ region[i].bufferOffset = ((FFVkBuffer *)dst[i]->data)->virtual_offset;
41824083 }
4183−
4184− (*nb_bufs)++;
4084+ } else {
4085+ /* Weird layout (3 planes, 2 buffers), patch welcome, fallback to copy */
4086+ return AVERROR_PATCHWELCOME;
41854087 }
41864088
41874089 return 0;
@@ -4228,6 +4130,21 @@ static int vulkan_transfer_frame(AVHWFramesContext *hwfc, · 40 unmodified lines
42284130 if (swf->width > hwfc->width || swf->height > hwfc->height)
42294131 return AVERROR(EINVAL);
42304132
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+
42314148 /* Setup buffers first */
42324149 if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY) {
42334150 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