diff mbox series

[FFmpeg-devel] hwcontext_vulkan: make 2 public functions always available

Message ID MpwId0_--3-2@lynne.ee
State New
Headers show
Series [FFmpeg-devel] hwcontext_vulkan: make 2 public functions always available | expand

Checks

Context Check Description
andriy/make_x86 fail Make failed
andriy/make_ppc fail Make failed

Commit Message

Lynne Dec. 2, 2021, 6:01 p.m. UTC
The issue is that if ffmpeg is compiled without Vulkan, and an API 
user includes and uses the functions exposed in hwcontext_vulkan.h,
then a linking error will happen, as the hwcontext_vulkan.c file has
not been compiled.

Move the functions to another file, and make it always compiled. The
functions do not use any Vulkan functions.

Patch attached.
Subject: [PATCH] hwcontext_vulkan: make 2 public functions always available

The issue is that if ffmpeg is compiled without Vulkan, and an API
user includes and uses the functions exposed in hwcontext_vulkan.h,
then a linking error will happen, as the hwcontext_vulkan.c file has
not been compiled.

Move the functions to another file, and make it always compiled. The
functions do not use any Vulkan functions.
---
 libavutil/Makefile                  |   1 +
 libavutil/hwcontext_vulkan.c        |  86 -----------------------
 libavutil/hwcontext_vulkan_common.c | 105 ++++++++++++++++++++++++++++
 3 files changed, 106 insertions(+), 86 deletions(-)
 create mode 100644 libavutil/hwcontext_vulkan_common.c

Comments

James Almer Dec. 2, 2021, 6:09 p.m. UTC | #1
On Thu, Dec 2, 2021 at 3:01 PM Lynne <dev@lynne.ee> wrote:

> The issue is that if ffmpeg is compiled without Vulkan, and an API
> user includes and uses the functions exposed in hwcontext_vulkan.h,
> then a linking error will happen, as the hwcontext_vulkan.c file has
> not been compiled.
>
> Move the functions to another file, and make it always compiled. The
> functions do not use any Vulkan functions.
>
> Patch attached.
>

Do what avcodec/d3d11va.c does in this new file and return NULL/ENOSYS when
CONFIG_VULKAN is 0. You have to because all the Vulkan pixfmt defines will
not be available on environments without the Vulkan headers.
Andreas Rheinhardt Dec. 2, 2021, 6:13 p.m. UTC | #2
Lynne:
> The issue is that if ffmpeg is compiled without Vulkan, and an API 
> user includes and uses the functions exposed in hwcontext_vulkan.h,
> then a linking error will happen, as the hwcontext_vulkan.c file has
> not been compiled.
> 
> Move the functions to another file, and make it always compiled. The
> functions do not use any Vulkan functions.
> 
> Patch attached.
> 
> 

1. Isn't a linking error exactly what is intended in such cases?
2. And even if not: Actually compiling the whole implementation is
unnecessary; in such cases we typically #if everything away (e.g. in
your case: it will always return NULL).
3. The hwcontext_vulkan.h header requires vulkan system headers; you
can't compile this without it.

- Andreas
Michael Niedermayer Dec. 3, 2021, 9:51 a.m. UTC | #3
On Thu, Dec 02, 2021 at 07:01:08PM +0100, Lynne wrote:
> The issue is that if ffmpeg is compiled without Vulkan, and an API 
> user includes and uses the functions exposed in hwcontext_vulkan.h,
> then a linking error will happen, as the hwcontext_vulkan.c file has
> not been compiled.
> 
> Move the functions to another file, and make it always compiled. The
> functions do not use any Vulkan functions.
> 
> Patch attached.

>  Makefile                  |    1 
>  hwcontext_vulkan.c        |   86 -------------------------------------
>  hwcontext_vulkan_common.c |  105 ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 106 insertions(+), 86 deletions(-)
> 8ad8f8dbe2c3e9695073e7a05f406865ae04d0f9  0001-hwcontext_vulkan-make-2-public-functions-always-avai.patch
> From ccd4aed173ea3e668ccf767d3a1ef6bef155ea48 Mon Sep 17 00:00:00 2001
> From: Lynne <dev@lynne.ee>
> Date: Thu, 2 Dec 2021 18:55:39 +0100
> Subject: [PATCH] hwcontext_vulkan: make 2 public functions always available

This breaks build on mingw64

In file included from src/libavutil/hwcontext_vulkan_common.c:19:0:
src/libavutil/hwcontext_vulkan.h:25:10: fatal error: vulkan/vulkan.h: No such file or directory
 #include <vulkan/vulkan.h>

thx

[...]
Niklas Haas Dec. 3, 2021, 12:59 p.m. UTC | #4
On Thu, 02 Dec 2021 19:13:17 +0100 Andreas Rheinhardt <andreas.rheinhardt@outlook.com> wrote:
> Lynne:
> > The issue is that if ffmpeg is compiled without Vulkan, and an API 
> > user includes and uses the functions exposed in hwcontext_vulkan.h,
> > then a linking error will happen, as the hwcontext_vulkan.c file has
> > not been compiled.
> > 
> > Move the functions to another file, and make it always compiled. The
> > functions do not use any Vulkan functions.
> > 
> > Patch attached.
> > 
> > 
> 
> 1. Isn't a linking error exactly what is intended in such cases?
> 2. And even if not: Actually compiling the whole implementation is
> unnecessary; in such cases we typically #if everything away (e.g. in
> your case: it will always return NULL).
> 3. The hwcontext_vulkan.h header requires vulkan system headers; you
> can't compile this without it.

Hi, I have a motivating use case: a single header library which needs to
conditionally use these functions only if they're supposed. My first
instinct was to test if the header is available/included, but that
doesn't work, because ffmpeg unconditionally installs it even if it's
not compiled (IMO wrong behavior).

If the only way to know whether or not the header works, is to perform a
build-time check to see if the functions link, that uncomfortably shifts
responsibility onto the API user of my library to perform this check on
their end before including my (single header) library.

This was one proposed work-around, which is to make them always link but
return a runtime error if FFmpeg was compiled without vulkan support.

I agree that in this case the entire file should be #if'd out and the
signatures implemented by stub functions that only return the necessary
error, with no build-time dependency on vulkan.h.
Hendrik Leppkes Dec. 3, 2021, 1:17 p.m. UTC | #5
On Thu, Dec 2, 2021 at 7:13 PM Andreas Rheinhardt
<andreas.rheinhardt@outlook.com> wrote:
>
> Lynne:
> > The issue is that if ffmpeg is compiled without Vulkan, and an API
> > user includes and uses the functions exposed in hwcontext_vulkan.h,
> > then a linking error will happen, as the hwcontext_vulkan.c file has
> > not been compiled.
> >
> > Move the functions to another file, and make it always compiled. The
> > functions do not use any Vulkan functions.
> >
> > Patch attached.
> >
> >
>
> 1. Isn't a linking error exactly what is intended in such cases?

Just do document what was already said on IRC:

I believe a stable ABI is important, and that includes always
exporting the same symbols on any given platform, no matter the build
configuration.
That way you can use binary distributions of our libraries without
needing to worry it was build just right, and use such optional
features when they are functional.

It was suggested to me that I should just dlsym any "optional"
features, but thats really forcing a lot of complexity on any user-app
just to save a few bytes of stub functions to ensure linking or
dynamic loading works.

I believe we have in the past included stubs for APIs that might not
be functional at all times, and we should continue to do so and patch
any holes that might have crept up here.

- Hendrik
Hendrik Leppkes Dec. 3, 2021, 1:20 p.m. UTC | #6
On Thu, Dec 2, 2021 at 7:13 PM Andreas Rheinhardt
<andreas.rheinhardt@outlook.com> wrote:
> 2. And even if not: Actually compiling the whole implementation is
> unnecessary; in such cases we typically #if everything away (e.g. in
> your case: it will always return NULL).
> 3. The hwcontext_vulkan.h header requires vulkan system headers; you
> can't compile this without it.
>

I meant to put this into the other mail, but I agree with these two
points. Obviously we can't expect that vulkan headers are always
available, so these "always available" functions should just be empty
stubs that return NULL when vulkan is not enabled at compile time.

- Hendrik
Anton Khirnov Dec. 6, 2021, 10:31 a.m. UTC | #7
Quoting Hendrik Leppkes (2021-12-03 14:17:44)
> On Thu, Dec 2, 2021 at 7:13 PM Andreas Rheinhardt
> <andreas.rheinhardt@outlook.com> wrote:
> >
> > Lynne:
> > > The issue is that if ffmpeg is compiled without Vulkan, and an API
> > > user includes and uses the functions exposed in hwcontext_vulkan.h,
> > > then a linking error will happen, as the hwcontext_vulkan.c file has
> > > not been compiled.
> > >
> > > Move the functions to another file, and make it always compiled. The
> > > functions do not use any Vulkan functions.
> > >
> > > Patch attached.
> > >
> > >
> >
> > 1. Isn't a linking error exactly what is intended in such cases?
> 
> Just do document what was already said on IRC:
> 
> I believe a stable ABI is important, and that includes always
> exporting the same symbols on any given platform, no matter the build
> configuration.
> That way you can use binary distributions of our libraries without
> needing to worry it was build just right, and use such optional
> features when they are functional.
> 
> It was suggested to me that I should just dlsym any "optional"
> features, but thats really forcing a lot of complexity on any user-app
> just to save a few bytes of stub functions to ensure linking or
> dynamic loading works.
> 
> I believe we have in the past included stubs for APIs that might not
> be functional at all times, and we should continue to do so and patch
> any holes that might have crept up here.

I agree with this and have added such stubs in the past.
diff mbox series

Patch

diff --git a/libavutil/Makefile b/libavutil/Makefile
index 529046dbc8..3cf2de19ec 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -174,6 +174,7 @@  OBJS = adler32.o                                                        \
        tx_int32.o                                                       \
        video_enc_params.o                                               \
        film_grain_params.o                                              \
+       hwcontext_vulkan_common.o                                        \
 
 
 OBJS-$(CONFIG_CUDA)                     += hwcontext_cuda.o
diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
index a0437c9661..4465287ab7 100644
--- a/libavutil/hwcontext_vulkan.c
+++ b/libavutil/hwcontext_vulkan.c
@@ -153,87 +153,6 @@  typedef struct AVVkFrameInternal {
         av_free((void *)props);                                                \
     }
 
-static const struct {
-    enum AVPixelFormat pixfmt;
-    const VkFormat vkfmts[4];
-} vk_pixfmt_map[] = {
-    { AV_PIX_FMT_GRAY8,   { VK_FORMAT_R8_UNORM } },
-    { AV_PIX_FMT_GRAY16,  { VK_FORMAT_R16_UNORM } },
-    { AV_PIX_FMT_GRAYF32, { VK_FORMAT_R32_SFLOAT } },
-
-    { AV_PIX_FMT_NV12, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM } },
-    { AV_PIX_FMT_NV21, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM } },
-    { AV_PIX_FMT_P010, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
-    { AV_PIX_FMT_P016, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
-
-    { AV_PIX_FMT_NV16, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM } },
-
-    { AV_PIX_FMT_NV24, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM } },
-    { AV_PIX_FMT_NV42, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM } },
-
-    { AV_PIX_FMT_YUV420P,   {  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM } },
-    { AV_PIX_FMT_YUV420P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-    { AV_PIX_FMT_YUV420P12, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-    { AV_PIX_FMT_YUV420P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-
-    { AV_PIX_FMT_YUV422P,   {  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM } },
-    { AV_PIX_FMT_YUV422P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-    { AV_PIX_FMT_YUV422P12, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-    { AV_PIX_FMT_YUV422P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-
-    { AV_PIX_FMT_YUV444P,   {  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM } },
-    { AV_PIX_FMT_YUV444P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-    { AV_PIX_FMT_YUV444P12, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-    { AV_PIX_FMT_YUV444P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-
-    { AV_PIX_FMT_YUVA420P,   {  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM } },
-    { AV_PIX_FMT_YUVA420P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-    /* There is no AV_PIX_FMT_YUVA420P12 */
-    { AV_PIX_FMT_YUVA420P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-
-    { AV_PIX_FMT_YUVA422P,   {  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM } },
-    { AV_PIX_FMT_YUVA422P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-    { AV_PIX_FMT_YUVA422P12, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-    { AV_PIX_FMT_YUVA422P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-
-    { AV_PIX_FMT_YUVA444P,   {  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM } },
-    { AV_PIX_FMT_YUVA444P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-    { AV_PIX_FMT_YUVA444P12, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-    { AV_PIX_FMT_YUVA444P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-
-    { AV_PIX_FMT_BGRA,   { VK_FORMAT_B8G8R8A8_UNORM } },
-    { AV_PIX_FMT_RGBA,   { VK_FORMAT_R8G8B8A8_UNORM } },
-    { AV_PIX_FMT_RGB24,  { VK_FORMAT_R8G8B8_UNORM } },
-    { AV_PIX_FMT_BGR24,  { VK_FORMAT_B8G8R8_UNORM } },
-    { AV_PIX_FMT_RGB48,  { VK_FORMAT_R16G16B16_UNORM } },
-    { AV_PIX_FMT_RGBA64, { VK_FORMAT_R16G16B16A16_UNORM } },
-    { AV_PIX_FMT_RGBA64, { VK_FORMAT_R16G16B16A16_UNORM } },
-    { AV_PIX_FMT_RGB565, { VK_FORMAT_R5G6B5_UNORM_PACK16 } },
-    { AV_PIX_FMT_BGR565, { VK_FORMAT_B5G6R5_UNORM_PACK16 } },
-    { AV_PIX_FMT_BGR0,   { VK_FORMAT_B8G8R8A8_UNORM } },
-    { AV_PIX_FMT_RGB0,   { VK_FORMAT_R8G8B8A8_UNORM } },
-
-    /* Lower priority as there's an endianess-dependent overlap between these
-     * and rgba/bgr0, and PACK32 formats are more limited */
-    { AV_PIX_FMT_BGR32,  { VK_FORMAT_A8B8G8R8_UNORM_PACK32 } },
-    { AV_PIX_FMT_0BGR32, { VK_FORMAT_A8B8G8R8_UNORM_PACK32 } },
-
-    { AV_PIX_FMT_X2RGB10, { VK_FORMAT_A2R10G10B10_UNORM_PACK32 } },
-
-    { AV_PIX_FMT_GBRAP, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } },
-    { AV_PIX_FMT_GBRAP16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-    { AV_PIX_FMT_GBRPF32, { VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT } },
-    { AV_PIX_FMT_GBRAPF32, { VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT } },
-};
-
-const VkFormat *av_vkfmt_from_pixfmt(enum AVPixelFormat p)
-{
-    for (enum AVPixelFormat i = 0; i < FF_ARRAY_ELEMS(vk_pixfmt_map); i++)
-        if (vk_pixfmt_map[i].pixfmt == p)
-            return vk_pixfmt_map[i].vkfmts;
-    return NULL;
-}
-
 static int pixfmt_is_supported(AVHWDeviceContext *dev_ctx, enum AVPixelFormat p,
                                int linear)
 {
@@ -3876,11 +3795,6 @@  static int vulkan_frames_derive_to(AVHWFramesContext *dst_fc,
     return vulkan_frames_init(dst_fc);
 }
 
-AVVkFrame *av_vk_frame_alloc(void)
-{
-    return av_mallocz(sizeof(AVVkFrame));
-}
-
 const HWContextType ff_hwcontext_type_vulkan = {
     .type                   = AV_HWDEVICE_TYPE_VULKAN,
     .name                   = "Vulkan",
diff --git a/libavutil/hwcontext_vulkan_common.c b/libavutil/hwcontext_vulkan_common.c
new file mode 100644
index 0000000000..23bef0404b
--- /dev/null
+++ b/libavutil/hwcontext_vulkan_common.c
@@ -0,0 +1,105 @@ 
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "hwcontext_vulkan.h"
+
+static const struct {
+    enum AVPixelFormat pixfmt;
+    const VkFormat vkfmts[4];
+} vk_pixfmt_map[] = {
+    { AV_PIX_FMT_GRAY8,   { VK_FORMAT_R8_UNORM } },
+    { AV_PIX_FMT_GRAY16,  { VK_FORMAT_R16_UNORM } },
+    { AV_PIX_FMT_GRAYF32, { VK_FORMAT_R32_SFLOAT } },
+
+    { AV_PIX_FMT_NV12, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM } },
+    { AV_PIX_FMT_NV21, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM } },
+    { AV_PIX_FMT_P010, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
+    { AV_PIX_FMT_P016, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
+
+    { AV_PIX_FMT_NV16, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM } },
+
+    { AV_PIX_FMT_NV24, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM } },
+    { AV_PIX_FMT_NV42, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM } },
+
+    { AV_PIX_FMT_YUV420P,   {  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM } },
+    { AV_PIX_FMT_YUV420P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+    { AV_PIX_FMT_YUV420P12, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+    { AV_PIX_FMT_YUV420P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+
+    { AV_PIX_FMT_YUV422P,   {  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM } },
+    { AV_PIX_FMT_YUV422P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+    { AV_PIX_FMT_YUV422P12, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+    { AV_PIX_FMT_YUV422P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+
+    { AV_PIX_FMT_YUV444P,   {  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM } },
+    { AV_PIX_FMT_YUV444P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+    { AV_PIX_FMT_YUV444P12, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+    { AV_PIX_FMT_YUV444P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+
+    { AV_PIX_FMT_YUVA420P,   {  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM } },
+    { AV_PIX_FMT_YUVA420P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+    /* There is no AV_PIX_FMT_YUVA420P12 */
+    { AV_PIX_FMT_YUVA420P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+
+    { AV_PIX_FMT_YUVA422P,   {  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM } },
+    { AV_PIX_FMT_YUVA422P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+    { AV_PIX_FMT_YUVA422P12, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+    { AV_PIX_FMT_YUVA422P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+
+    { AV_PIX_FMT_YUVA444P,   {  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM } },
+    { AV_PIX_FMT_YUVA444P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+    { AV_PIX_FMT_YUVA444P12, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+    { AV_PIX_FMT_YUVA444P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+
+    { AV_PIX_FMT_BGRA,   { VK_FORMAT_B8G8R8A8_UNORM } },
+    { AV_PIX_FMT_RGBA,   { VK_FORMAT_R8G8B8A8_UNORM } },
+    { AV_PIX_FMT_RGB24,  { VK_FORMAT_R8G8B8_UNORM } },
+    { AV_PIX_FMT_BGR24,  { VK_FORMAT_B8G8R8_UNORM } },
+    { AV_PIX_FMT_RGB48,  { VK_FORMAT_R16G16B16_UNORM } },
+    { AV_PIX_FMT_RGBA64, { VK_FORMAT_R16G16B16A16_UNORM } },
+    { AV_PIX_FMT_RGBA64, { VK_FORMAT_R16G16B16A16_UNORM } },
+    { AV_PIX_FMT_RGB565, { VK_FORMAT_R5G6B5_UNORM_PACK16 } },
+    { AV_PIX_FMT_BGR565, { VK_FORMAT_B5G6R5_UNORM_PACK16 } },
+    { AV_PIX_FMT_BGR0,   { VK_FORMAT_B8G8R8A8_UNORM } },
+    { AV_PIX_FMT_RGB0,   { VK_FORMAT_R8G8B8A8_UNORM } },
+
+    /* Lower priority as there's an endianess-dependent overlap between these
+     * and rgba/bgr0, and PACK32 formats are more limited */
+    { AV_PIX_FMT_BGR32,  { VK_FORMAT_A8B8G8R8_UNORM_PACK32 } },
+    { AV_PIX_FMT_0BGR32, { VK_FORMAT_A8B8G8R8_UNORM_PACK32 } },
+
+    { AV_PIX_FMT_X2RGB10, { VK_FORMAT_A2R10G10B10_UNORM_PACK32 } },
+
+    { AV_PIX_FMT_GBRAP, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } },
+    { AV_PIX_FMT_GBRAP16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+    { AV_PIX_FMT_GBRPF32, { VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT } },
+    { AV_PIX_FMT_GBRAPF32, { VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT } },
+};
+
+const VkFormat *av_vkfmt_from_pixfmt(enum AVPixelFormat p)
+{
+    for (enum AVPixelFormat i = 0; i < FF_ARRAY_ELEMS(vk_pixfmt_map); i++)
+        if (vk_pixfmt_map[i].pixfmt == p)
+            return vk_pixfmt_map[i].vkfmts;
+    return NULL;
+}
+
+AVVkFrame *av_vk_frame_alloc(void)
+{
+    return av_mallocz(sizeof(AVVkFrame));
+}