summaryrefslogtreecommitdiff
path: root/libavutil
diff options
context:
space:
mode:
authorLynne <dev@lynne.ee>2020-03-12 18:01:07 +0000
committerLynne <dev@lynne.ee>2020-03-12 18:16:11 +0000
commit501bd57bdbc488db93c95d40682ef0b4f01ccec5 (patch)
treea84a2b81ca301a8a1fd08f00a42b431a3c81171d /libavutil
parent9086af2a0a590c7f576b72379d1708392cd96d5c (diff)
downloadffmpeg-501bd57bdbc488db93c95d40682ef0b4f01ccec5.tar.gz
hwcontext_vulkan: initialize semaphores of DMABUF imports
There was a recent change in Intel's driver that triggered a driver-internal error if the semaphore given to the command buffer wasn't initialized. Given that the specifications require the semaphore to be initialized, this is within spec. Unlike what's causing it in the first place, which is that there are no ways to extract/import dma sync objects from DMABUFs, so we must leave our semaphores bare.
Diffstat (limited to 'libavutil')
-rw-r--r--libavutil/hwcontext_vulkan.c51
1 files changed, 38 insertions, 13 deletions
diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
index 51fdbd2489..6c2372f7fb 100644
--- a/libavutil/hwcontext_vulkan.c
+++ b/libavutil/hwcontext_vulkan.c
@@ -1139,12 +1139,19 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f,
return 0;
}
-static int prepare_frame(AVHWFramesContext *hwfc, AVVkFrame *frame)
+enum PrepMode {
+ PREP_MODE_WRITE,
+ PREP_MODE_RO_SHADER,
+};
+
+static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx,
+ AVVkFrame *frame, enum PrepMode pmode)
{
VkResult ret;
+ VkImageLayout new_layout;
+ VkAccessFlags new_access;
AVHWDeviceContext *ctx = hwfc->device_ctx;
AVVulkanDeviceContext *hwctx = ctx->hwctx;
- VulkanFramesPriv *s = hwfc->internal->priv;
const int planes = av_pix_fmt_count_planes(hwfc->sw_format);
VkImageMemoryBarrier img_bar[AV_NUM_DATA_POINTERS] = { 0 };
@@ -1157,13 +1164,24 @@ static int prepare_frame(AVHWFramesContext *hwfc, AVVkFrame *frame)
VkSubmitInfo s_info = {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.commandBufferCount = 1,
- .pCommandBuffers = &s->cmd.buf,
+ .pCommandBuffers = &ectx->buf,
.pSignalSemaphores = frame->sem,
.signalSemaphoreCount = planes,
};
- ret = vkBeginCommandBuffer(s->cmd.buf, &cmd_start);
+ switch (pmode) {
+ case PREP_MODE_WRITE:
+ new_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ new_access = VK_ACCESS_TRANSFER_WRITE_BIT;
+ break;
+ case PREP_MODE_RO_SHADER:
+ new_layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+ new_access = VK_ACCESS_TRANSFER_READ_BIT;
+ break;
+ }
+
+ ret = vkBeginCommandBuffer(ectx->buf, &cmd_start);
if (ret != VK_SUCCESS)
return AVERROR_EXTERNAL;
@@ -1173,9 +1191,9 @@ static int prepare_frame(AVHWFramesContext *hwfc, AVVkFrame *frame)
for (int i = 0; i < planes; i++) {
img_bar[i].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
img_bar[i].srcAccessMask = 0x0;
- img_bar[i].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ img_bar[i].dstAccessMask = new_access;
img_bar[i].oldLayout = frame->layout[i];
- img_bar[i].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ img_bar[i].newLayout = new_layout;
img_bar[i].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
img_bar[i].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
img_bar[i].image = frame->img[i];
@@ -1187,20 +1205,20 @@ static int prepare_frame(AVHWFramesContext *hwfc, AVVkFrame *frame)
frame->access[i] = img_bar[i].dstAccessMask;
}
- vkCmdPipelineBarrier(s->cmd.buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ vkCmdPipelineBarrier(ectx->buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
0, NULL, 0, NULL, planes, img_bar);
- ret = vkEndCommandBuffer(s->cmd.buf);
+ ret = vkEndCommandBuffer(ectx->buf);
if (ret != VK_SUCCESS)
return AVERROR_EXTERNAL;
- ret = vkQueueSubmit(s->cmd.queue, 1, &s_info, s->cmd.fence);
+ ret = vkQueueSubmit(ectx->queue, 1, &s_info, ectx->fence);
if (ret != VK_SUCCESS) {
return AVERROR_EXTERNAL;
} else {
- vkWaitForFences(hwctx->act_dev, 1, &s->cmd.fence, VK_TRUE, UINT64_MAX);
- vkResetFences(hwctx->act_dev, 1, &s->cmd.fence);
+ vkWaitForFences(hwctx->act_dev, 1, &ectx->fence, VK_TRUE, UINT64_MAX);
+ vkResetFences(hwctx->act_dev, 1, &ectx->fence);
}
return 0;
@@ -1371,7 +1389,7 @@ static AVBufferRef *vulkan_pool_alloc(void *opaque, int size)
if (err)
goto fail;
- err = prepare_frame(hwfc, f);
+ err = prepare_frame(hwfc, &p->cmd, f, PREP_MODE_WRITE);
if (err)
goto fail;
@@ -1775,7 +1793,7 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f
/* We'd import a semaphore onto the one we created using
* vkImportSemaphoreFdKHR but unfortunately neither DRM nor VAAPI
* offer us anything we could import and sync with, so instead
- * leave the semaphore unsignalled and enjoy the validation spam. */
+ * just signal the semaphore we created. */
f->layout[i] = image_create_info.initialLayout;
f->access[i] = 0x0;
@@ -1796,6 +1814,13 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f
return AVERROR_EXTERNAL;
}
+ /* NOTE: This is completely uneccesary and unneeded once we can import
+ * semaphores from DRM. Otherwise we have to activate the semaphores.
+ * We're reusing the exec context that's also used for uploads/downloads. */
+ err = prepare_frame(hwfc, &p->cmd, f, PREP_MODE_RO_SHADER);
+ if (err)
+ goto fail;
+
*frame = f;
return 0;