Bug Summary

File:root/firefox-clang/media/ffvpx/libavutil/vulkan.c
Warning:line 338, column 13
Access to field 'sem' results in a dereference of a null pointer (loaded from variable 'e')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name vulkan.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/media/ffvpx/libavutil -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/media/ffvpx/libavutil -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -include libavutil_visibility.h -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D HAVE_AV_CONFIG_H -D ASSERT_LEVEL=2 -I /root/firefox-clang/media/ffvpx/libavutil -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/media/ffvpx/libavutil -I /root/firefox-clang/third_party/khronos/vulkan-headers/include -I /root/firefox-clang/media/mozva -I /root/firefox-clang/third_party/drm/drm -I /root/firefox-clang/third_party/drm/drm/include -I /root/firefox-clang/third_party/drm/drm/include/libdrm -I /root/firefox-clang/media/ffvpx -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=tautological-type-limit-compare -Wno-range-loop-analysis -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-unknown-warning-option -Wno-character-conversion -Wno-parentheses -Wno-pointer-sign -Wno-sign-compare -Wno-switch -Wno-type-limits -Wno-unused-function -Wno-deprecated-declarations -Wno-absolute-value -Wno-incompatible-pointer-types -Wno-string-conversion -Wno-visibility -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-10-17-231001-351276-1 -x c /root/firefox-clang/media/ffvpx/libavutil/vulkan.c
1/*
2 * Copyright (c) Lynne
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "config.h"
22#include <stdlib.h>
23#include "avassert.h"
24#include "mem.h"
25#include "refstruct.h"
26
27#include "vulkan.h"
28#include "libavutil/vulkan_loader.h"
29
30#if CONFIG_SHADER_COMPRESSION0
31#include "libavutil/zlib_utils.h"
32#endif
33
34const VkComponentMapping ff_comp_identity_map = {
35 .r = VK_COMPONENT_SWIZZLE_IDENTITY,
36 .g = VK_COMPONENT_SWIZZLE_IDENTITY,
37 .b = VK_COMPONENT_SWIZZLE_IDENTITY,
38 .a = VK_COMPONENT_SWIZZLE_IDENTITY,
39};
40
41/* Converts return values to strings */
42const char *ff_vk_ret2str(VkResult res)
43{
44#define CASE(VAL) case VAL: return #VAL
45 switch (res) {
46 CASE(VK_SUCCESS);
47 CASE(VK_NOT_READY);
48 CASE(VK_TIMEOUT);
49 CASE(VK_EVENT_SET);
50 CASE(VK_EVENT_RESET);
51 CASE(VK_INCOMPLETE);
52 CASE(VK_ERROR_OUT_OF_HOST_MEMORY);
53 CASE(VK_ERROR_OUT_OF_DEVICE_MEMORY);
54 CASE(VK_ERROR_INITIALIZATION_FAILED);
55 CASE(VK_ERROR_DEVICE_LOST);
56 CASE(VK_ERROR_MEMORY_MAP_FAILED);
57 CASE(VK_ERROR_LAYER_NOT_PRESENT);
58 CASE(VK_ERROR_EXTENSION_NOT_PRESENT);
59 CASE(VK_ERROR_FEATURE_NOT_PRESENT);
60 CASE(VK_ERROR_INCOMPATIBLE_DRIVER);
61 CASE(VK_ERROR_TOO_MANY_OBJECTS);
62 CASE(VK_ERROR_FORMAT_NOT_SUPPORTED);
63 CASE(VK_ERROR_FRAGMENTED_POOL);
64 CASE(VK_ERROR_UNKNOWN);
65 CASE(VK_ERROR_OUT_OF_POOL_MEMORY);
66 CASE(VK_ERROR_INVALID_EXTERNAL_HANDLE);
67 CASE(VK_ERROR_FRAGMENTATION);
68 CASE(VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS);
69 CASE(VK_PIPELINE_COMPILE_REQUIRED);
70 CASE(VK_ERROR_SURFACE_LOST_KHR);
71 CASE(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR);
72 CASE(VK_SUBOPTIMAL_KHR);
73 CASE(VK_ERROR_OUT_OF_DATE_KHR);
74 CASE(VK_ERROR_INCOMPATIBLE_DISPLAY_KHR);
75 CASE(VK_ERROR_VALIDATION_FAILED_EXT);
76 CASE(VK_ERROR_INVALID_SHADER_NV);
77 CASE(VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR);
78 CASE(VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR);
79 CASE(VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR);
80 CASE(VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR);
81 CASE(VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR);
82 CASE(VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT);
83 CASE(VK_ERROR_NOT_PERMITTED_KHR);
84 CASE(VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT);
85 CASE(VK_THREAD_IDLE_KHR);
86 CASE(VK_THREAD_DONE_KHR);
87 CASE(VK_OPERATION_DEFERRED_KHR);
88 CASE(VK_OPERATION_NOT_DEFERRED_KHR);
89 default: return "Unknown error";
90 }
91#undef CASE
92}
93
94/* Malitia pura, Khronos */
95#define FN_MAP_TO(dst_t, dst_name, src_t, src_name) \
96 dst_t ff_vk_map_ ##src_name## _to_ ##dst_name(src_t src) \
97 { \
98 dst_t dst = 0x0; \
99 MAP_TO(VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT, \
100 VK_IMAGE_USAGE_SAMPLED_BIT); \
101 MAP_TO(VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT, \
102 VK_IMAGE_USAGE_TRANSFER_SRC_BIT); \
103 MAP_TO(VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT, \
104 VK_IMAGE_USAGE_TRANSFER_DST_BIT); \
105 MAP_TO(VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT, \
106 VK_IMAGE_USAGE_STORAGE_BIT); \
107 MAP_TO(VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT, \
108 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); \
109 MAP_TO(VK_FORMAT_FEATURE_2_VIDEO_DECODE_OUTPUT_BIT_KHR, \
110 VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR); \
111 MAP_TO(VK_FORMAT_FEATURE_2_VIDEO_DECODE_DPB_BIT_KHR, \
112 VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR); \
113 MAP_TO(VK_FORMAT_FEATURE_2_VIDEO_ENCODE_DPB_BIT_KHR, \
114 VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR); \
115 MAP_TO(VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR, \
116 VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR); \
117 MAP_TO(VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT, \
118 VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT); \
119 return dst; \
120 }
121
122#define MAP_TO(flag1, flag2) if (src & flag2) dst |= flag1;
123FN_MAP_TO(VkFormatFeatureFlagBits2, feats, VkImageUsageFlags, usage)
124#undef MAP_TO
125#define MAP_TO(flag1, flag2) if (src & flag1) dst |= flag2;
126FN_MAP_TO(VkImageUsageFlags, usage, VkFormatFeatureFlagBits2, feats)
127#undef MAP_TO
128#undef FN_MAP_TO
129
130static void load_enabled_qfs(FFVulkanContext *s)
131{
132 s->nb_qfs = 0;
133 for (int i = 0; i < s->hwctx->nb_qf; i++) {
134 /* Skip duplicates */
135 int skip = 0;
136 for (int j = 0; j < s->nb_qfs; j++) {
137 if (s->qfs[j] == s->hwctx->qf[i].idx) {
138 skip = 1;
139 break;
140 }
141 }
142 if (skip)
143 continue;
144
145 s->qfs[s->nb_qfs++] = s->hwctx->qf[i].idx;
146 }
147}
148
149static void reset_imageviews(AVRefStructOpaque unused, void *obj);
150
151int ff_vk_load_props(FFVulkanContext *s)
152{
153 FFVulkanFunctions *vk = &s->vkfn;
154
155 s->props = (VkPhysicalDeviceProperties2) {
156 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
157 };
158
159 FF_VK_STRUCT_EXT(s, &s->props, &s->props_11, FF_VK_EXT_NO_FLAG,do { if (((1ULL << 63) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 63))) { (&s->props_11)
->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES
; ff_vk_link_struct(&s->props, &s->props_11); }
} while (0)
160 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES)do { if (((1ULL << 63) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 63))) { (&s->props_11)
->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES
; ff_vk_link_struct(&s->props, &s->props_11); }
} while (0)
;
161 FF_VK_STRUCT_EXT(s, &s->props, &s->driver_props, FF_VK_EXT_NO_FLAG,do { if (((1ULL << 63) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 63))) { (&s->driver_props
)->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES
; ff_vk_link_struct(&s->props, &s->driver_props
); } } while (0)
162 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES)do { if (((1ULL << 63) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 63))) { (&s->driver_props
)->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES
; ff_vk_link_struct(&s->props, &s->driver_props
); } } while (0)
;
163 FF_VK_STRUCT_EXT(s, &s->props, &s->subgroup_props, FF_VK_EXT_NO_FLAG,do { if (((1ULL << 63) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 63))) { (&s->subgroup_props
)->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES
; ff_vk_link_struct(&s->props, &s->subgroup_props
); } } while (0)
164 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES)do { if (((1ULL << 63) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 63))) { (&s->subgroup_props
)->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES
; ff_vk_link_struct(&s->props, &s->subgroup_props
); } } while (0)
;
165
166 FF_VK_STRUCT_EXT(s, &s->props, &s->push_desc_props, FF_VK_EXT_PUSH_DESCRIPTOR,do { if (((1ULL << 14) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 14))) { (&s->push_desc_props
)->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR
; ff_vk_link_struct(&s->props, &s->push_desc_props
); } } while (0)
167 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR)do { if (((1ULL << 14) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 14))) { (&s->push_desc_props
)->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR
; ff_vk_link_struct(&s->props, &s->push_desc_props
); } } while (0)
;
168 FF_VK_STRUCT_EXT(s, &s->props, &s->hprops, FF_VK_EXT_EXTERNAL_HOST_MEMORY,do { if (((1ULL << 4) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 4))) { (&s->hprops)->
sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT
; ff_vk_link_struct(&s->props, &s->hprops); } }
while (0)
169 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT)do { if (((1ULL << 4) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 4))) { (&s->hprops)->
sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT
; ff_vk_link_struct(&s->props, &s->hprops); } }
while (0)
;
170 FF_VK_STRUCT_EXT(s, &s->props, &s->coop_matrix_props, FF_VK_EXT_COOP_MATRIX,do { if (((1ULL << 11) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 11))) { (&s->coop_matrix_props
)->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_KHR
; ff_vk_link_struct(&s->props, &s->coop_matrix_props
); } } while (0)
171 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_KHR)do { if (((1ULL << 11) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 11))) { (&s->coop_matrix_props
)->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_KHR
; ff_vk_link_struct(&s->props, &s->coop_matrix_props
); } } while (0)
;
172 FF_VK_STRUCT_EXT(s, &s->props, &s->optical_flow_props, FF_VK_EXT_OPTICAL_FLOW,do { if (((1ULL << 12) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 12))) { (&s->optical_flow_props
)->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_PROPERTIES_NV
; ff_vk_link_struct(&s->props, &s->optical_flow_props
); } } while (0)
173 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_PROPERTIES_NV)do { if (((1ULL << 12) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 12))) { (&s->optical_flow_props
)->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_PROPERTIES_NV
; ff_vk_link_struct(&s->props, &s->optical_flow_props
); } } while (0)
;
174 FF_VK_STRUCT_EXT(s, &s->props, &s->host_image_props, FF_VK_EXT_HOST_IMAGE_COPY,do { if (((1ULL << 18) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 18))) { (&s->host_image_props
)->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES_EXT
; ff_vk_link_struct(&s->props, &s->host_image_props
); } } while (0)
175 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES_EXT)do { if (((1ULL << 18) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 18))) { (&s->host_image_props
)->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES_EXT
; ff_vk_link_struct(&s->props, &s->host_image_props
); } } while (0)
;
176
177#ifdef VK_EXT_shader_long_vector1
178 FF_VK_STRUCT_EXT(s, &s->props, &s->long_vector_props, FF_VK_EXT_LONG_VECTOR,do { if (((1ULL << 22) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 22))) { (&s->long_vector_props
)->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_LONG_VECTOR_PROPERTIES_EXT
; ff_vk_link_struct(&s->props, &s->long_vector_props
); } } while (0)
179 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_LONG_VECTOR_PROPERTIES_EXT)do { if (((1ULL << 22) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 22))) { (&s->long_vector_props
)->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_LONG_VECTOR_PROPERTIES_EXT
; ff_vk_link_struct(&s->props, &s->long_vector_props
); } } while (0)
;
180#endif
181
182 s->feats = (VkPhysicalDeviceFeatures2) {
183 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
184 };
185
186 FF_VK_STRUCT_EXT(s, &s->feats, &s->feats_12, FF_VK_EXT_NO_FLAG,do { if (((1ULL << 63) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 63))) { (&s->feats_12)
->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES
; ff_vk_link_struct(&s->feats, &s->feats_12); }
} while (0)
187 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES)do { if (((1ULL << 63) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 63))) { (&s->feats_12)
->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES
; ff_vk_link_struct(&s->feats, &s->feats_12); }
} while (0)
;
188 FF_VK_STRUCT_EXT(s, &s->feats, &s->atomic_float_feats, FF_VK_EXT_ATOMIC_FLOAT,do { if (((1ULL << 10) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 10))) { (&s->atomic_float_feats
)->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT
; ff_vk_link_struct(&s->feats, &s->atomic_float_feats
); } } while (0)
189 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT)do { if (((1ULL << 10) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 10))) { (&s->atomic_float_feats
)->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT
; ff_vk_link_struct(&s->feats, &s->atomic_float_feats
); } } while (0)
;
190#ifdef VK_KHR_unified_image_layouts1
191 FF_VK_STRUCT_EXT(s, &s->feats, &s->unified_layout_feats, FF_VK_EXT_UNIFIED_IMAGE_LAYOUTS,do { if (((1ULL << 26) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 26))) { (&s->unified_layout_feats
)->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFIED_IMAGE_LAYOUTS_FEATURES_KHR
; ff_vk_link_struct(&s->feats, &s->unified_layout_feats
); } } while (0)
192 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFIED_IMAGE_LAYOUTS_FEATURES_KHR)do { if (((1ULL << 26) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 26))) { (&s->unified_layout_feats
)->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFIED_IMAGE_LAYOUTS_FEATURES_KHR
; ff_vk_link_struct(&s->feats, &s->unified_layout_feats
); } } while (0)
;
193#endif
194
195 if (!s->imageviews_pool) {
196 s->imageviews_pool = av_refstruct_pool_alloc_ext(sizeof(FFVkImageViews), 0,
197 NULL((void*)0), NULL((void*)0), reset_imageviews,
198 NULL((void*)0), NULL((void*)0));
199 if (!s->imageviews_pool)
200 return AVERROR(ENOMEM)(-(12));
201 }
202
203 /* Try allocating 1024 layouts */
204 s->host_image_copy_layouts = av_malloc(sizeof(*s->host_image_copy_layouts)*1024);
205 s->host_image_props.pCopySrcLayouts = s->host_image_copy_layouts;
206 s->host_image_props.copySrcLayoutCount = 512;
207 s->host_image_props.pCopyDstLayouts = s->host_image_copy_layouts + 512;
208 s->host_image_props.copyDstLayoutCount = 512;
209
210 vk->GetPhysicalDeviceProperties2(s->hwctx->phys_dev, &s->props);
211
212 /* Check if we had enough memory for all layouts */
213 if (s->host_image_props.copySrcLayoutCount == 512 ||
214 s->host_image_props.copyDstLayoutCount == 512) {
215 VkImageLayout *new_array;
216 size_t new_size;
217 s->host_image_props.pCopySrcLayouts =
218 s->host_image_props.pCopyDstLayouts = NULL((void*)0);
219 s->host_image_props.copySrcLayoutCount =
220 s->host_image_props.copyDstLayoutCount = 0;
221 vk->GetPhysicalDeviceProperties2(s->hwctx->phys_dev, &s->props);
222
223 new_size = s->host_image_props.copySrcLayoutCount +
224 s->host_image_props.copyDstLayoutCount;
225 new_size *= sizeof(*s->host_image_copy_layouts);
226 new_array = av_realloc(s->host_image_copy_layouts, new_size);
227 if (!new_array)
228 return AVERROR(ENOMEM)(-(12));
229
230 s->host_image_copy_layouts = new_array;
231 s->host_image_props.pCopySrcLayouts = new_array;
232 s->host_image_props.pCopyDstLayouts = new_array + s->host_image_props.copySrcLayoutCount;
233 vk->GetPhysicalDeviceProperties2(s->hwctx->phys_dev, &s->props);
234 }
235
236 vk->GetPhysicalDeviceMemoryProperties(s->hwctx->phys_dev, &s->mprops);
237 vk->GetPhysicalDeviceFeatures2(s->hwctx->phys_dev, &s->feats);
238
239 for (int i = 0; i < s->mprops.memoryTypeCount; i++)
240 s->host_cached_flag |= s->mprops.memoryTypes[i].propertyFlags &
241 VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
242
243 load_enabled_qfs(s);
244
245 if (s->qf_props)
246 return 0;
247
248 vk->GetPhysicalDeviceQueueFamilyProperties2(s->hwctx->phys_dev, &s->tot_nb_qfs, NULL((void*)0));
249
250 s->qf_props = av_calloc(s->tot_nb_qfs, sizeof(*s->qf_props));
251 if (!s->qf_props)
252 return AVERROR(ENOMEM)(-(12));
253
254 s->query_props = av_calloc(s->tot_nb_qfs, sizeof(*s->query_props));
255 if (!s->qf_props) {
256 av_freep(&s->qf_props);
257 return AVERROR(ENOMEM)(-(12));
258 }
259
260 s->video_props = av_calloc(s->tot_nb_qfs, sizeof(*s->video_props));
261 if (!s->video_props) {
262 av_freep(&s->qf_props);
263 av_freep(&s->query_props);
264 return AVERROR(ENOMEM)(-(12));
265 }
266
267#ifdef VK_KHR_maintenance91
268 s->ownership_props = av_calloc(s->tot_nb_qfs, sizeof(*s->ownership_props));
269 if (!s->ownership_props) {
270 av_freep(&s->qf_props);
271 av_freep(&s->query_props);
272 av_freep(&s->video_props);
273 return AVERROR(ENOMEM)(-(12));
274 }
275#endif
276
277 for (uint32_t i = 0; i < s->tot_nb_qfs; i++) {
278 s->qf_props[i] = (VkQueueFamilyProperties2) {
279 .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2,
280 };
281
282 FF_VK_STRUCT_EXT(s, &s->qf_props[i], &s->query_props[i], FF_VK_EXT_VIDEO_QUEUE,do { if (((1ULL << 36) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 36))) { (&s->query_props
[i])->sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_KHR
; ff_vk_link_struct(&s->qf_props[i], &s->query_props
[i]); } } while (0)
283 VK_STRUCTURE_TYPE_QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_KHR)do { if (((1ULL << 36) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 36))) { (&s->query_props
[i])->sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_KHR
; ff_vk_link_struct(&s->qf_props[i], &s->query_props
[i]); } } while (0)
;
284 FF_VK_STRUCT_EXT(s, &s->qf_props[i], &s->video_props[i], FF_VK_EXT_VIDEO_QUEUE,do { if (((1ULL << 36) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 36))) { (&s->video_props
[i])->sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR
; ff_vk_link_struct(&s->qf_props[i], &s->video_props
[i]); } } while (0)
285 VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR)do { if (((1ULL << 36) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 36))) { (&s->video_props
[i])->sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR
; ff_vk_link_struct(&s->qf_props[i], &s->video_props
[i]); } } while (0)
;
286#ifdef VK_KHR_maintenance91
287 FF_VK_STRUCT_EXT(s, &s->qf_props[i], &s->ownership_props[i], FF_VK_EXT_MAINTENANCE_9,do { if (((1ULL << 25) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 25))) { (&s->ownership_props
[i])->sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_OWNERSHIP_TRANSFER_PROPERTIES_KHR
; ff_vk_link_struct(&s->qf_props[i], &s->ownership_props
[i]); } } while (0)
288 VK_STRUCTURE_TYPE_QUEUE_FAMILY_OWNERSHIP_TRANSFER_PROPERTIES_KHR)do { if (((1ULL << 25) == (1ULL << 63)) || ((s)->
extensions & (1ULL << 25))) { (&s->ownership_props
[i])->sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_OWNERSHIP_TRANSFER_PROPERTIES_KHR
; ff_vk_link_struct(&s->qf_props[i], &s->ownership_props
[i]); } } while (0)
;
289#endif
290 }
291
292 vk->GetPhysicalDeviceQueueFamilyProperties2(s->hwctx->phys_dev, &s->tot_nb_qfs, s->qf_props);
293
294 if (s->extensions & FF_VK_EXT_COOP_MATRIX(1ULL << 11)) {
295 vk->GetPhysicalDeviceCooperativeMatrixPropertiesKHR(s->hwctx->phys_dev,
296 &s->coop_mat_props_nb, NULL((void*)0));
297
298 if (s->coop_mat_props_nb) {
299 s->coop_mat_props = av_malloc_array(s->coop_mat_props_nb,
300 sizeof(VkCooperativeMatrixPropertiesKHR));
301 for (int i = 0; i < s->coop_mat_props_nb; i++) {
302 s->coop_mat_props[i] = (VkCooperativeMatrixPropertiesKHR) {
303 .sType = VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_KHR,
304 };
305 }
306
307 vk->GetPhysicalDeviceCooperativeMatrixPropertiesKHR(s->hwctx->phys_dev,
308 &s->coop_mat_props_nb,
309 s->coop_mat_props);
310 }
311 }
312
313 return 0;
314}
315
316AVVulkanDeviceQueueFamily *ff_vk_qf_find(FFVulkanContext *s,
317 VkQueueFlagBits dev_family,
318 VkVideoCodecOperationFlagBitsKHR vid_ops)
319{
320 for (int i = 0; i < s->hwctx->nb_qf; i++) {
321 if ((s->hwctx->qf[i].flags & dev_family) &&
322 (s->hwctx->qf[i].video_caps & vid_ops) == vid_ops) {
323 return &s->hwctx->qf[i];
324 }
325 }
326 return NULL((void*)0);
327}
328
329static void exec_discard_deps(FFVulkanContext *s, FFVkExecContext *e);
330
331void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool)
332{
333 FFVulkanFunctions *vk = &s->vkfn;
334
335 for (int i = 0; i < pool->pool_size; i++) {
16
Assuming 'i' is < field 'pool_size'
17
Loop condition is true. Entering loop body
336 FFVkExecContext *e = &pool->contexts[i];
18
'e' initialized to a null pointer value
337
338 if (e->sem) {
19
Access to field 'sem' results in a dereference of a null pointer (loaded from variable 'e')
339 VkSemaphoreWaitInfo sem_wait_info = {
340 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
341 .semaphoreCount = 1,
342 .pSemaphores = &e->sem,
343 .pValues = &e->sem_value,
344 };
345 vk->WaitSemaphores(s->hwctx->act_dev, &sem_wait_info, UINT64_MAX(18446744073709551615UL));
346 vk->DestroySemaphore(s->hwctx->act_dev, e->sem, s->hwctx->alloc);
347 }
348
349 exec_discard_deps(s, e);
350 pthread_mutex_destroystrict_pthread_mutex_destroy(&e->lock);
351 }
352
353 /* Free shader-specific data */
354 for (int i = 0; i < pool->nb_reg_shd; i++) {
355 FFVulkanShaderData *sd = &pool->reg_shd[i];
356
357 if (sd->desc_pool)
358 vk->DestroyDescriptorPool(s->hwctx->act_dev, sd->desc_pool,
359 s->hwctx->alloc);
360
361 av_freep(&sd->desc_sets);
362 }
363 pool->nb_reg_shd = 0;
364
365 for (int i = 0; i < pool->pool_size; i++) {
366 if (pool->cmd_buf_pools[i])
367 vk->FreeCommandBuffers(s->hwctx->act_dev, pool->cmd_buf_pools[i],
368 1, &pool->cmd_bufs[i]);
369
370 if (pool->cmd_buf_pools[i])
371 vk->DestroyCommandPool(s->hwctx->act_dev, pool->cmd_buf_pools[i], s->hwctx->alloc);
372 }
373 if (pool->query_pool)
374 vk->DestroyQueryPool(s->hwctx->act_dev, pool->query_pool, s->hwctx->alloc);
375
376 av_free(pool->query_data);
377 av_free(pool->cmd_buf_pools);
378 av_free(pool->cmd_bufs);
379 av_free(pool->contexts);
380 pool->pool_size = 0;
381}
382
383/* Per-family, per-library queue selection phases; each library links its own
384 * copy, and pools which benefit from spreading are created by the same one */
385static atomic_uint exec_pool_phase[FF_ARRAY_ELEMS(((AVVulkanDeviceContext *)NULL)->qf)(sizeof(((AVVulkanDeviceContext *)((void*)0))->qf) / sizeof
((((AVVulkanDeviceContext *)((void*)0))->qf)[0]))
];
386static AVOncepthread_once_t exec_pool_phase_seeded = AV_ONCE_INIT0;
387
388static void exec_pool_phase_seed(void)
389{
390 uint32_t seed = rand();
391 for (int i = 0; i < FF_ARRAY_ELEMS(exec_pool_phase)(sizeof(exec_pool_phase) / sizeof((exec_pool_phase)[0])); i++)
392 atomic_store_explicit__c11_atomic_store(&exec_pool_phase[i], seed, memory_order_relaxed);
393}
394
395int ff_vk_exec_pool_init(FFVulkanContext *s, AVVulkanDeviceQueueFamily *qf,
396 FFVkExecPool *pool, int nb_contexts,
397 int nb_queries, VkQueryType query_type, int query_64bit,
398 const void *query_create_pnext)
399{
400 int err;
401 VkResult ret;
402 FFVulkanFunctions *vk = &s->vkfn;
403
404 VkCommandPoolCreateInfo cqueue_create;
405 VkCommandBufferAllocateInfo cbuf_create;
406
407 const VkQueryPoolVideoEncodeFeedbackCreateInfoKHR *ef = NULL((void*)0);
408
409 atomic_init__c11_atomic_init(&pool->idx, 0);
410
411 if (query_type == VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR) {
1
Assuming 'query_type' is not equal to VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR
2
Taking false branch
412 ef = ff_vk_find_struct(query_create_pnext,
413 VK_STRUCTURE_TYPE_QUERY_POOL_VIDEO_ENCODE_FEEDBACK_CREATE_INFO_KHR);
414 if (!ef)
415 return AVERROR(EINVAL)(-(22));
416 }
417
418 /* Allocate space for command buffer pools */
419 pool->cmd_buf_pools = av_malloc(nb_contexts*sizeof(*pool->cmd_buf_pools));
420 if (!pool->cmd_buf_pools) {
3
Assuming field 'cmd_buf_pools' is non-null
4
Taking false branch
421 err = AVERROR(ENOMEM)(-(12));
422 goto fail;
423 }
424
425 /* Allocate space for command buffers */
426 pool->cmd_bufs = av_malloc(nb_contexts*sizeof(*pool->cmd_bufs));
427 if (!pool->cmd_bufs) {
5
Assuming field 'cmd_bufs' is non-null
6
Taking false branch
428 err = AVERROR(ENOMEM)(-(12));
429 goto fail;
430 }
431
432 for (int i = 0; i < nb_contexts; i++) {
7
Assuming 'i' is >= 'nb_contexts'
8
Loop condition is false. Execution continues on line 468
433 /* Create command pool */
434 cqueue_create = (VkCommandPoolCreateInfo) {
435 .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
436 .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT |
437 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
438 .queueFamilyIndex = qf->idx,
439 };
440
441 ret = vk->CreateCommandPool(s->hwctx->act_dev, &cqueue_create,
442 s->hwctx->alloc, &pool->cmd_buf_pools[i]);
443 if (ret != VK_SUCCESS) {
444 av_log(s, AV_LOG_ERROR16, "Command pool creation failure: %s\n",
445 ff_vk_ret2str(ret));
446 err = AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
447 goto fail;
448 }
449
450 /* Allocate command buffer */
451 cbuf_create = (VkCommandBufferAllocateInfo) {
452 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
453 .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
454 .commandPool = pool->cmd_buf_pools[i],
455 .commandBufferCount = 1,
456 };
457 ret = vk->AllocateCommandBuffers(s->hwctx->act_dev, &cbuf_create,
458 &pool->cmd_bufs[i]);
459 if (ret != VK_SUCCESS) {
460 av_log(s, AV_LOG_ERROR16, "Command buffer alloc failure: %s\n",
461 ff_vk_ret2str(ret));
462 err = AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
463 goto fail;
464 }
465 }
466
467 /* Query pool */
468 if (nb_queries) {
9
Assuming 'nb_queries' is 0
10
Taking false branch
469 VkQueryPoolCreateInfo query_pool_info = {
470 .sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
471 .pNext = query_create_pnext,
472 .queryType = query_type,
473 .queryCount = nb_queries*nb_contexts,
474 };
475 ret = vk->CreateQueryPool(s->hwctx->act_dev, &query_pool_info,
476 s->hwctx->alloc, &pool->query_pool);
477 if (ret != VK_SUCCESS) {
478 av_log(s, AV_LOG_ERROR16, "Query pool alloc failure: %s\n",
479 ff_vk_ret2str(ret));
480 err = AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
481 goto fail;
482 }
483
484 pool->nb_queries = nb_queries;
485 pool->query_status_stride = 1 + 1; /* One result, one status by default */
486 pool->query_results = nb_queries;
487 pool->query_statuses = nb_queries;
488
489 /* Video encode queries produce two results per query */
490 if (query_type == VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR) {
491 int nb_results = av_popcountav_popcount_c(ef->encodeFeedbackFlags);
492 pool->query_status_stride = nb_results + 1;
493 pool->query_results *= nb_results;
494 } else if (query_type == VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR) {
495 pool->query_status_stride = 1;
496 pool->query_results = 0;
497 }
498
499 pool->qd_size = (pool->query_results + pool->query_statuses)*(query_64bit ? 8 : 4);
500
501 /* Allocate space for the query data */
502 pool->query_data = av_calloc(nb_contexts, pool->qd_size);
503 if (!pool->query_data) {
504 err = AVERROR(ENOMEM)(-(12));
505 goto fail;
506 }
507 }
508
509 /* Allocate space for the contexts */
510 pool->contexts = av_calloc(nb_contexts, sizeof(*pool->contexts));
11
Value assigned to field 'contexts'
511 if (!pool->contexts) {
12
Assuming field 'contexts' is null
13
Taking true branch
512 err = AVERROR(ENOMEM)(-(12));
513 goto fail;
14
Control jumps to line 590
514 }
515
516 pool->pool_size = nb_contexts;
517
518 for (int i = 0; i < pool->pool_size; i++)
519 pthread_mutex_initstrict_pthread_mutex_init(&pool->contexts[i].lock, NULL((void*)0));
520
521#ifdef VK_KHR_internally_synchronized_queues1
522 /* Check if the extension and its flag are actually enabled */
523 int internal_queue_sync = 0;
524 if (s->extensions & FF_VK_EXT_INTERNAL_QUEUE_SYNC(1ULL << 23)) {
525 const VkPhysicalDeviceInternallySynchronizedQueuesFeaturesKHR *iqs;
526 iqs = ff_vk_find_struct(s->hwctx->device_features.pNext,
527 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INTERNALLY_SYNCHRONIZED_QUEUES_FEATURES_KHR);
528 internal_queue_sync = iqs && iqs->internallySynchronizedQueues;
529 }
530#endif
531
532 /* Video pools are pinned to the phase-picked queue (sessions order their
533 * execution anyway); all other pools rotate starting from it, so pools
534 * advancing in lockstep do not collide. */
535 av_assert1(qf->idx < FF_ARRAY_ELEMS(exec_pool_phase))do { if (!(qf->idx < (sizeof(exec_pool_phase) / sizeof(
(exec_pool_phase)[0])))) { av_log(((void*)0), 0, "Assertion %s failed at %s:%d\n"
, "qf->idx < (sizeof(exec_pool_phase) / sizeof((exec_pool_phase)[0]))"
, "/root/firefox-clang/media/ffvpx/libavutil/vulkan.c", 535);
abort(); } } while (0)
;
536 ff_thread_once(&exec_pool_phase_seeded, exec_pool_phase_seed)strict_pthread_once(&exec_pool_phase_seeded, exec_pool_phase_seed
)
;
537 uint32_t phase = atomic_fetch_add(&exec_pool_phase[qf->idx], 1)__c11_atomic_fetch_add(&exec_pool_phase[qf->idx], 1, 5
)
;
538 int pin_queue = qf->flags & (VK_QUEUE_VIDEO_DECODE_BIT_KHR |
539 VK_QUEUE_VIDEO_ENCODE_BIT_KHR);
540
541 /* Init contexts */
542 for (int i = 0; i < pool->pool_size; i++) {
543 FFVkExecContext *e = &pool->contexts[i];
544 VkSemaphoreTypeCreateInfo sem_type = {
545 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
546 .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE,
547 };
548 VkSemaphoreCreateInfo sem_create = {
549 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
550 .pNext = &sem_type,
551 };
552
553 /* Timeline semaphore carrying the busy state */
554 ret = vk->CreateSemaphore(s->hwctx->act_dev, &sem_create, s->hwctx->alloc,
555 &e->sem);
556 if (ret != VK_SUCCESS) {
557 av_log(s, AV_LOG_ERROR16, "Failed to create submission semaphore: %s\n",
558 ff_vk_ret2str(ret));
559 return AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
560 }
561
562 e->idx = i;
563 e->parent = pool;
564
565 /* Query data */
566 e->query_data = ((uint8_t *)pool->query_data) + pool->qd_size*i;
567 e->query_idx = nb_queries*i;
568
569 /* Command buffer */
570 e->buf = pool->cmd_bufs[i];
571
572 /* Queue index distribution */
573 e->qi = pin_queue ? phase % qf->num : (i + phase) % qf->num;
574 e->qf = qf->idx;
575 VkDeviceQueueInfo2 qinfo = {
576 .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2,
577#ifdef VK_KHR_internally_synchronized_queues1
578 .flags = internal_queue_sync ?
579 VK_DEVICE_QUEUE_CREATE_INTERNALLY_SYNCHRONIZED_BIT_KHR : 0,
580#endif
581 .queueFamilyIndex = qf->idx,
582 .queueIndex = e->qi,
583 };
584 vk->GetDeviceQueue2(s->hwctx->act_dev, &qinfo, &e->queue);
585 }
586
587 return 0;
588
589fail:
590 ff_vk_exec_pool_free(s, pool);
15
Calling 'ff_vk_exec_pool_free'
591 return err;
592}
593
594VkResult ff_vk_exec_get_query(FFVulkanContext *s, FFVkExecContext *e,
595 void **data, VkQueryResultFlagBits flags)
596{
597 FFVulkanFunctions *vk = &s->vkfn;
598 const FFVkExecPool *pool = e->parent;
599 VkQueryResultFlags qf = flags & ~(VK_QUERY_RESULT_64_BIT |
600 VK_QUERY_RESULT_WITH_STATUS_BIT_KHR);
601
602 if (!e->query_data) {
603 av_log(s, AV_LOG_ERROR16, "Requested a query with a NULL query_data pointer!\n");
604 return VK_INCOMPLETE;
605 }
606
607 qf |= pool->query_64bit ?
608 VK_QUERY_RESULT_64_BIT : 0x0;
609 qf |= pool->query_statuses ?
610 VK_QUERY_RESULT_WITH_STATUS_BIT_KHR : 0x0;
611
612 if (data)
613 *data = e->query_data;
614
615 return vk->GetQueryPoolResults(s->hwctx->act_dev, pool->query_pool,
616 e->query_idx,
617 pool->nb_queries,
618 pool->qd_size, e->query_data,
619 pool->qd_size, qf);
620}
621
622FFVkExecContext *ff_vk_exec_get(FFVulkanContext *s, FFVkExecPool *pool)
623{
624 FFVulkanFunctions *vk = &s->vkfn;
625
626 /* Release the dependencies of every completed context, rather than leaving them held until reuse */
627 for (int i = 0; i < pool->pool_size; i++) {
628 uint64_t sem_val;
629 FFVkExecContext *e = &pool->contexts[i];
630 if (pthread_mutex_trylock(&e->lock))
631 continue; /* In use by a recording or submitting thread */
632 /* Busy contexts (counter below sem_value) are claimed or executing:
633 * their dependency lists are off-limits */
634 if (vk->GetSemaphoreCounterValue(s->hwctx->act_dev, e->sem, &sem_val) == VK_SUCCESS &&
635 sem_val >= e->sem_value &&
636 (e->nb_buf_deps || e->nb_refstruct_deps || e->nb_obj_deps ||
637 e->nb_frame_deps || e->nb_sw_frame_deps))
638 exec_discard_deps(s, e);
639 pthread_mutex_unlockstrict_pthread_mutex_unlock(&e->lock);
640 }
641
642 return &pool->contexts[atomic_fetch_add(&pool->idx, 1)__c11_atomic_fetch_add(&pool->idx, 1, 5) % pool->pool_size];
643}
644
645void ff_vk_exec_wait(FFVulkanContext *s, FFVkExecContext *e)
646{
647 FFVulkanFunctions *vk = &s->vkfn;
648 VkSemaphoreWaitInfo sem_wait_info = {
649 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
650 .semaphoreCount = 1,
651 .pSemaphores = &e->sem,
652 .pValues = &e->sem_value,
653 };
654 pthread_mutex_lockstrict_pthread_mutex_lock(&e->lock);
655 vk->WaitSemaphores(s->hwctx->act_dev, &sem_wait_info, UINT64_MAX(18446744073709551615UL));
656 exec_discard_deps(s, e);
657 pthread_mutex_unlockstrict_pthread_mutex_unlock(&e->lock);
658}
659
660int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e)
661{
662 VkResult ret;
663 FFVulkanFunctions *vk = &s->vkfn;
664 const FFVkExecPool *pool = e->parent;
665
666 VkCommandBufferBeginInfo cmd_start = {
667 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
668 .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
669 };
670 VkSemaphoreWaitInfo sem_wait_info = {
671 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
672 .semaphoreCount = 1,
673 .pSemaphores = &e->sem,
674 .pValues = &e->sem_value,
675 };
676
677 pthread_mutex_lockstrict_pthread_mutex_lock(&e->lock);
678
679 /* Wait out the context's previous execution */
680 vk->WaitSemaphores(s->hwctx->act_dev, &sem_wait_info, UINT64_MAX(18446744073709551615UL));
681
682 /* Discard queue dependencies */
683 exec_discard_deps(s, e);
684
685 ret = vk->BeginCommandBuffer(e->buf, &cmd_start);
686 if (ret != VK_SUCCESS) {
687 av_log(s, AV_LOG_ERROR16, "Failed to start command recoding: %s\n",
688 ff_vk_ret2str(ret));
689 pthread_mutex_unlockstrict_pthread_mutex_unlock(&e->lock);
690 return AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
691 }
692
693 if (pool->nb_queries)
694 vk->CmdResetQueryPool(e->buf, pool->query_pool,
695 e->query_idx, pool->nb_queries);
696
697 /* Claim: the semaphore stays below this value until submission completes
698 * or the recording is discarded, keeping every other user away */
699 e->sem_value++;
700 e->sem_sig[e->sem_sig_cnt++] = (VkSemaphoreSubmitInfo) {
701 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
702 .semaphore = e->sem,
703 .value = e->sem_value,
704 .stageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
705 };
706
707 pthread_mutex_unlockstrict_pthread_mutex_unlock(&e->lock);
708
709 return 0;
710}
711
712static void exec_discard_deps(FFVulkanContext *s, FFVkExecContext *e)
713{
714 FFVulkanFunctions *vk = &s->vkfn;
715
716 for (int j = 0; j < e->nb_buf_deps; j++)
717 av_buffer_unref(&e->buf_deps[j]);
718 e->nb_buf_deps = 0;
719
720 for (int j = 0; j < e->nb_refstruct_deps; j++)
721 av_refstruct_unref(&e->refstruct_deps[j]);
722 e->nb_refstruct_deps = 0;
723
724 for (int j = 0; j < e->nb_obj_deps; j++) {
725 FFVkExecObjDep *od = &e->obj_deps[j];
726 switch (od->type) {
727 case VK_OBJECT_TYPE_IMAGE_VIEW:
728 vk->DestroyImageView(s->hwctx->act_dev,
729 (VkImageView)od->obj, s->hwctx->alloc);
730 break;
731 case VK_OBJECT_TYPE_SEMAPHORE:
732 vk->DestroySemaphore(s->hwctx->act_dev,
733 (VkSemaphore)od->obj, s->hwctx->alloc);
734 break;
735 default:
736 av_assert1(0)do { if (!(0)) { av_log(((void*)0), 0, "Assertion %s failed at %s:%d\n"
, "0", "/root/firefox-clang/media/ffvpx/libavutil/vulkan.c", 736
); abort(); } } while (0)
;
737 }
738 }
739 e->nb_obj_deps = 0;
740
741 for (int j = 0; j < e->nb_sw_frame_deps; j++)
742 av_frame_free(&e->sw_frame_deps[j]);
743 e->nb_sw_frame_deps = 0;
744
745 for (int j = 0; j < e->nb_frame_deps; j++) {
746 AVFrame *f = e->frame_deps[j];
747 if (e->frame_locked[j]) {
748 AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
749 AVVulkanFramesContext *vkfc = hwfc->hwctx;
750 AVVkFrame *vkf = (AVVkFrame *)f->data[0];
751 vkfc->unlock_frame(hwfc, vkf);
752 e->frame_locked[j] = 0;
753 }
754 e->frame_update[j] = 0;
755 }
756 e->nb_frame_deps = 0;
757
758 e->sem_wait_cnt = 0;
759 e->sem_sig_cnt = 0;
760 e->sem_sig_val_dst_cnt = 0;
761}
762
763void ff_vk_exec_discard(FFVulkanContext *s, FFVkExecContext *e)
764{
765 FFVulkanFunctions *vk = &s->vkfn;
766 VkSemaphoreSignalInfo sig_info = {
767 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO,
768 .semaphore = e->sem,
769 .value = e->sem_value,
770 };
771
772 /* An abandoned recording is exclusively the claimer's: free everything
773 * without the mutex, and un-claim last by signalling the burnt generation */
774 exec_discard_deps(s, e);
775 vk->ResetCommandBuffer(e->buf, 0);
776 vk->SignalSemaphore(s->hwctx->act_dev, &sig_info);
777}
778
779void ff_vk_exec_add_dep_refstruct(FFVulkanContext *s, FFVkExecContext *e,
780 void *obj)
781{
782 av_assert1(e->nb_refstruct_deps < FF_VK_EXEC_MAX_BUF_DEPS)do { if (!(e->nb_refstruct_deps < 256)) { av_log(((void
*)0), 0, "Assertion %s failed at %s:%d\n", "e->nb_refstruct_deps < 256"
, "/root/firefox-clang/media/ffvpx/libavutil/vulkan.c", 782);
abort(); } } while (0)
;
783 e->refstruct_deps[e->nb_refstruct_deps++] = av_refstruct_ref(obj);
784}
785
786void ff_vk_exec_move_dep_refstruct(FFVulkanContext *s, FFVkExecContext *e,
787 void *obj)
788{
789 void **ptr = obj;
790
791 av_assert1(e->nb_refstruct_deps < FF_VK_EXEC_MAX_BUF_DEPS)do { if (!(e->nb_refstruct_deps < 256)) { av_log(((void
*)0), 0, "Assertion %s failed at %s:%d\n", "e->nb_refstruct_deps < 256"
, "/root/firefox-clang/media/ffvpx/libavutil/vulkan.c", 791);
abort(); } } while (0)
;
792
793 for (int i = 0; i < e->nb_refstruct_deps; i++) {
794 if (e->refstruct_deps[i] == *ptr) {
795 av_refstruct_unref(obj);
796 return;
797 }
798 }
799
800 e->refstruct_deps[e->nb_refstruct_deps++] = *ptr;
801 *ptr = NULL((void*)0);
802}
803
804void ff_vk_exec_add_dep_obj(FFVulkanContext *s, FFVkExecContext *e,
805 VkObjectType type, uint64_t obj)
806{
807 av_assert1(e->nb_obj_deps < FF_VK_EXEC_MAX_BUF_DEPS)do { if (!(e->nb_obj_deps < 256)) { av_log(((void*)0), 0
, "Assertion %s failed at %s:%d\n", "e->nb_obj_deps < 256"
, "/root/firefox-clang/media/ffvpx/libavutil/vulkan.c", 807);
abort(); } } while (0)
;
808 e->obj_deps[e->nb_obj_deps++] = (FFVkExecObjDep) { obj, type };
809}
810
811int ff_vk_exec_add_dep_sw_frame(FFVulkanContext *s, FFVkExecContext *e,
812 AVFrame *f)
813{
814 av_assert1(e->nb_sw_frame_deps < FF_VK_EXEC_MAX_SW_FRAME_DEPS)do { if (!(e->nb_sw_frame_deps < 16)) { av_log(((void*)
0), 0, "Assertion %s failed at %s:%d\n", "e->nb_sw_frame_deps < 16"
, "/root/firefox-clang/media/ffvpx/libavutil/vulkan.c", 814);
abort(); } } while (0)
;
815
816 e->sw_frame_deps[e->nb_sw_frame_deps] = av_frame_clone(f);
817 if (!e->sw_frame_deps[e->nb_sw_frame_deps])
818 return AVERROR(ENOMEM)(-(12));
819
820 e->nb_sw_frame_deps++;
821
822 return 0;
823}
824
825void ff_vk_exec_add_dep_wait_sem(FFVulkanContext *s, FFVkExecContext *e,
826 VkSemaphore sem, uint64_t val,
827 VkPipelineStageFlagBits2 stage)
828{
829 av_assert1(e->sem_wait_cnt < FF_VK_EXEC_MAX_SEM_OPS)do { if (!(e->sem_wait_cnt < (64*8))) { av_log(((void*)
0), 0, "Assertion %s failed at %s:%d\n", "e->sem_wait_cnt < (64*8)"
, "/root/firefox-clang/media/ffvpx/libavutil/vulkan.c", 829);
abort(); } } while (0)
;
830
831 e->sem_wait[e->sem_wait_cnt++] = (VkSemaphoreSubmitInfo) {
832 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
833 .semaphore = sem,
834 .value = val,
835 .stageMask = stage,
836 };
837}
838
839void ff_vk_exec_add_dep_signal_sem(FFVulkanContext *s, FFVkExecContext *e,
840 VkSemaphore sem, uint64_t val,
841 VkPipelineStageFlagBits2 stage)
842{
843 av_assert1(e->sem_sig_cnt < FF_VK_EXEC_MAX_SEM_OPS)do { if (!(e->sem_sig_cnt < (64*8))) { av_log(((void*)0
), 0, "Assertion %s failed at %s:%d\n", "e->sem_sig_cnt < (64*8)"
, "/root/firefox-clang/media/ffvpx/libavutil/vulkan.c", 843);
abort(); } } while (0)
;
844
845 e->sem_sig[e->sem_sig_cnt++] = (VkSemaphoreSubmitInfo) {
846 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
847 .semaphore = sem,
848 .value = val,
849 .stageMask = stage,
850 };
851}
852
853void ff_vk_exec_add_dep_bool_sem(FFVulkanContext *s, FFVkExecContext *e,
854 VkSemaphore *sem, int nb,
855 VkPipelineStageFlagBits2 stage,
856 int wait)
857{
858 /* Do not transfer ownership if we're signalling a binary semaphore,
859 * since we're probably exporting it. */
860 if (!wait) {
861 av_assert1((e->sem_sig_cnt + nb) <= FF_VK_EXEC_MAX_SEM_OPS)do { if (!((e->sem_sig_cnt + nb) <= (64*8))) { av_log((
(void*)0), 0, "Assertion %s failed at %s:%d\n", "(e->sem_sig_cnt + nb) <= (64*8)"
, "/root/firefox-clang/media/ffvpx/libavutil/vulkan.c", 861);
abort(); } } while (0)
;
862 for (int i = 0; i < nb; i++) {
863 e->sem_sig[e->sem_sig_cnt++] = (VkSemaphoreSubmitInfo) {
864 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
865 .semaphore = sem[i],
866 .stageMask = stage,
867 };
868 }
869
870 return;
871 }
872
873 /* Ownership of each semaphore passes to the execution */
874 for (int i = 0; i < nb; i++) {
875 ff_vk_exec_add_dep_obj(s, e, VK_OBJECT_TYPE_SEMAPHORE,
876 (uint64_t)sem[i]);
877 ff_vk_exec_add_dep_wait_sem(s, e, sem[i], 0, stage);
878 }
879}
880
881int ff_vk_exec_add_dep_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f,
882 VkPipelineStageFlagBits2 wait_stage,
883 VkPipelineStageFlagBits2 signal_stage)
884{
885 AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
886 AVVulkanFramesContext *vkfc = hwfc->hwctx;
887 AVVkFrame *vkf = (AVVkFrame *)f->data[0];
888 int nb_images = ff_vk_count_images(vkf);
889
890 /* Don't add duplicates */
891 for (int i = 0; i < e->nb_frame_deps; i++)
892 if (e->frame_deps[i]->data[0] == f->data[0])
893 return 1;
894
895 av_assert1(e->nb_frame_deps < FF_VK_EXEC_MAX_FRAME_DEPS)do { if (!(e->nb_frame_deps < 64)) { av_log(((void*)0),
0, "Assertion %s failed at %s:%d\n", "e->nb_frame_deps < 64"
, "/root/firefox-clang/media/ffvpx/libavutil/vulkan.c", 895);
abort(); } } while (0)
;
896 av_assert1((e->sem_wait_cnt + nb_images) <= FF_VK_EXEC_MAX_SEM_OPS)do { if (!((e->sem_wait_cnt + nb_images) <= (64*8))) { av_log
(((void*)0), 0, "Assertion %s failed at %s:%d\n", "(e->sem_wait_cnt + nb_images) <= (64*8)"
, "/root/firefox-clang/media/ffvpx/libavutil/vulkan.c", 896);
abort(); } } while (0)
;
897 av_assert1((e->sem_sig_cnt + nb_images) <= FF_VK_EXEC_MAX_SEM_OPS)do { if (!((e->sem_sig_cnt + nb_images) <= (64*8))) { av_log
(((void*)0), 0, "Assertion %s failed at %s:%d\n", "(e->sem_sig_cnt + nb_images) <= (64*8)"
, "/root/firefox-clang/media/ffvpx/libavutil/vulkan.c", 897);
abort(); } } while (0)
;
898
899 /* prepare_frame in hwcontext_vulkan.c uses the regular frame management
900 * code but has no frame yet, and it doesn't need to actually store a ref
901 * to the frame. */
902 if (f->buf[0]) {
903 av_assert1(e->nb_buf_deps < FF_VK_EXEC_MAX_BUF_DEPS)do { if (!(e->nb_buf_deps < 256)) { av_log(((void*)0), 0
, "Assertion %s failed at %s:%d\n", "e->nb_buf_deps < 256"
, "/root/firefox-clang/media/ffvpx/libavutil/vulkan.c", 903);
abort(); } } while (0)
;
904 e->buf_deps[e->nb_buf_deps] = av_buffer_ref(f->buf[0]);
905 if (!e->buf_deps[e->nb_buf_deps])
906 return AVERROR(ENOMEM)(-(12));
907 e->nb_buf_deps++;
908 }
909
910 e->frame_deps[e->nb_frame_deps] = f;
911
912 vkfc->lock_frame(hwfc, vkf);
913 e->frame_locked[e->nb_frame_deps] = 1;
914 e->frame_update[e->nb_frame_deps] = 0;
915 e->nb_frame_deps++;
916
917 for (int i = 0; i < nb_images; i++) {
918 e->sem_wait[e->sem_wait_cnt++] = (VkSemaphoreSubmitInfo) {
919 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
920 .semaphore = vkf->sem[i],
921 .value = vkf->sem_value[i],
922 .stageMask = wait_stage,
923 };
924
925 e->sem_sig[e->sem_sig_cnt++] = (VkSemaphoreSubmitInfo) {
926 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
927 .semaphore = vkf->sem[i],
928 .value = vkf->sem_value[i] + 1,
929 .stageMask = signal_stage,
930 };
931
932 e->sem_sig_val_dst[e->sem_sig_val_dst_cnt] = &vkf->sem_value[i];
933 e->sem_sig_val_dst_cnt++;
934 }
935
936 return 0;
937}
938
939void ff_vk_exec_update_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f,
940 VkImageMemoryBarrier2 *bar, uint32_t *nb_img_bar)
941{
942 int i;
943 for (i = 0; i < e->nb_frame_deps; i++)
944 if (e->frame_deps[i]->data[0] == f->data[0])
945 break;
946 av_assert0(i < e->nb_frame_deps)do { if (!(i < e->nb_frame_deps)) { av_log(((void*)0), 0
, "Assertion %s failed at %s:%d\n", "i < e->nb_frame_deps"
, "/root/firefox-clang/media/ffvpx/libavutil/vulkan.c", 946);
abort(); } } while (0)
;
947
948 /* Don't update duplicates */
949 if (nb_img_bar && !e->frame_update[i])
950 (*nb_img_bar)++;
951
952 e->queue_family_dst[i] = bar->dstQueueFamilyIndex;
953 e->access_dst[i] = bar->dstAccessMask;
954 e->layout_dst[i] = bar->newLayout;
955 e->frame_update[i] = 1;
956}
957
958int ff_vk_exec_mirror_sem_value(FFVulkanContext *s, FFVkExecContext *e,
959 VkSemaphore *dst, uint64_t *dst_val,
960 AVFrame *f)
961{
962 AVVkFrame *vkf = (AVVkFrame *)f->data[0];
963
964 /* Reject unknown frames */
965 int i;
966 for (i = 0; i < e->nb_frame_deps; i++)
967 if (e->frame_deps[i]->data[0] == f->data[0])
968 break;
969 if (i == e->nb_frame_deps)
970 return AVERROR(EINVAL)(-(22));
971
972 av_assert1(e->sem_sig_val_dst_cnt < FF_VK_EXEC_MAX_SEM_OPS)do { if (!(e->sem_sig_val_dst_cnt < (64*8))) { av_log((
(void*)0), 0, "Assertion %s failed at %s:%d\n", "e->sem_sig_val_dst_cnt < (64*8)"
, "/root/firefox-clang/media/ffvpx/libavutil/vulkan.c", 972);
abort(); } } while (0)
;
973
974 *dst = vkf->sem[0];
975 *dst_val = vkf->sem_value[0];
976
977 e->sem_sig_val_dst[e->sem_sig_val_dst_cnt] = dst_val;
978 e->sem_sig_val_dst_cnt++;
979
980 return 0;
981}
982
983int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e)
984{
985 VkResult ret;
986 FFVulkanFunctions *vk = &s->vkfn;
987 VkCommandBufferSubmitInfo cmd_buf_info = (VkCommandBufferSubmitInfo) {
988 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
989 .commandBuffer = e->buf,
990 };
991 VkSubmitInfo2 submit_info = (VkSubmitInfo2) {
992 .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
993 .pCommandBufferInfos = &cmd_buf_info,
994 .commandBufferInfoCount = 1,
995 .pWaitSemaphoreInfos = e->sem_wait,
996 .waitSemaphoreInfoCount = e->sem_wait_cnt,
997 .pSignalSemaphoreInfos = e->sem_sig,
998 .signalSemaphoreInfoCount = e->sem_sig_cnt,
999 };
1000
1001 ret = vk->EndCommandBuffer(e->buf);
1002 if (ret != VK_SUCCESS) {
1003 av_log(s, AV_LOG_ERROR16, "Unable to finish command buffer: %s\n",
1004 ff_vk_ret2str(ret));
1005 ff_vk_exec_discard(s, e);
1006 return AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
1007 }
1008
1009#if FF_API_VULKAN_SYNC_QUEUES(61 < 62)
1010FF_DISABLE_DEPRECATION_WARNINGSGCC diagnostic push GCC diagnostic ignored "-Wdeprecated-declarations"
1011 s->hwctx->lock_queue(s->device, e->qf, e->qi);
1012FF_ENABLE_DEPRECATION_WARNINGSGCC diagnostic pop
1013#endif
1014 ret = vk->QueueSubmit2(e->queue, 1, &submit_info, VK_NULL_HANDLE((void*)0));
1015#if FF_API_VULKAN_SYNC_QUEUES(61 < 62)
1016FF_DISABLE_DEPRECATION_WARNINGSGCC diagnostic push GCC diagnostic ignored "-Wdeprecated-declarations"
1017 s->hwctx->unlock_queue(s->device, e->qf, e->qi);
1018FF_ENABLE_DEPRECATION_WARNINGSGCC diagnostic pop
1019#endif
1020
1021 if (ret != VK_SUCCESS) {
1022 av_log(s, AV_LOG_ERROR16, "Unable to submit command buffer: %s\n",
1023 ff_vk_ret2str(ret));
1024 /* This also un-claims the context by signalling its semaphore */
1025 ff_vk_exec_discard(s, e);
1026 return AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
1027 }
1028
1029 for (int i = 0; i < e->sem_sig_val_dst_cnt; i++)
1030 *e->sem_sig_val_dst[i] += 1;
1031
1032 /* Unlock all frames */
1033 for (int j = 0; j < e->nb_frame_deps; j++) {
1034 if (e->frame_locked[j]) {
1035 AVFrame *f = e->frame_deps[j];
1036 AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
1037 AVVulkanFramesContext *vkfc = hwfc->hwctx;
1038 AVVkFrame *vkf = (AVVkFrame *)f->data[0];
1039
1040 if (e->frame_update[j]) {
1041 int nb_images = ff_vk_count_images(vkf);
1042 for (int i = 0; i < nb_images; i++) {
1043 vkf->layout[i] = e->layout_dst[j];
1044 vkf->access[i] = e->access_dst[j];
1045 vkf->queue_family[i] = e->queue_family_dst[j];
1046 }
1047 }
1048 vkfc->unlock_frame(hwfc, vkf);
1049 e->frame_locked[j] = 0;
1050 }
1051 }
1052
1053 e->had_submission = 1;
1054
1055 return 0;
1056}
1057
1058int ff_vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req,
1059 VkMemoryPropertyFlagBits req_flags, void *alloc_extension,
1060 VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem)
1061{
1062 VkResult ret;
1063 int index = -1;
1064 FFVulkanFunctions *vk = &s->vkfn;
1065
1066 VkMemoryAllocateInfo alloc_info = {
1067 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
1068 .pNext = alloc_extension,
1069 };
1070
1071 alloc_info.allocationSize = req->size;
1072
1073 /* The vulkan spec requires memory types to be sorted in the "optimal"
1074 * order, so the first matching type we find will be the best/fastest one */
1075 for (int i = 0; i < s->mprops.memoryTypeCount; i++) {
1076 /* The memory type must be supported by the requirements (bitfield) */
1077 if (!(req->memoryTypeBits & (1 << i)))
1078 continue;
1079
1080 /* The memory type flags must include our properties */
1081 if ((req_flags != UINT32_MAX(4294967295U)) &&
1082 ((s->mprops.memoryTypes[i].propertyFlags & req_flags) != req_flags))
1083 continue;
1084
1085 /* Found a suitable memory type */
1086 index = i;
1087 break;
1088 }
1089
1090 if (index < 0) {
1091 av_log(s, AV_LOG_ERROR16, "No memory type found for flags 0x%x\n",
1092 req_flags);
1093 return AVERROR(EINVAL)(-(22));
1094 }
1095
1096 alloc_info.memoryTypeIndex = index;
1097
1098 ret = vk->AllocateMemory(s->hwctx->act_dev, &alloc_info,
1099 s->hwctx->alloc, mem);
1100 if (ret != VK_SUCCESS)
1101 return AVERROR(ENOMEM)(-(12));
1102
1103 if (mem_flags)
1104 *mem_flags |= s->mprops.memoryTypes[index].propertyFlags;
1105
1106 return 0;
1107}
1108
1109int ff_vk_image_create(FFVulkanContext *s, VkImage *img, VkDeviceMemory *mem,
1110 int width, int height, VkFormat format, int nb_layers,
1111 VkImageTiling tiling, VkImageUsageFlags usage,
1112 VkImageCreateFlags flags, void *create_pnext)
1113{
1114 int err;
1115 VkResult ret;
1116 FFVulkanFunctions *vk = &s->vkfn;
1117 VkMemoryPropertyFlagBits mem_flags;
1118
1119 VkImageCreateInfo create_info = {
1120 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
1121 .pNext = create_pnext,
1122 .flags = flags,
1123 .imageType = VK_IMAGE_TYPE_2D,
1124 .format = format,
1125 .extent = { width, height, 1 },
1126 .mipLevels = 1,
1127 .arrayLayers = nb_layers,
1128 .tiling = tiling,
1129 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
1130 .usage = usage,
1131 .samples = VK_SAMPLE_COUNT_1_BIT,
1132 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
1133 };
1134 VkMemoryDedicatedAllocateInfo ded_alloc = {
1135 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
1136 };
1137 VkMemoryRequirements2 req = {
1138 .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
1139 };
1140 VkImageMemoryRequirementsInfo2 req_desc = {
1141 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
1142 };
1143 VkBindImageMemoryInfo bind_info = {
1144 .sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
1145 };
1146
1147 *img = VK_NULL_HANDLE((void*)0);
1148 *mem = VK_NULL_HANDLE((void*)0);
1149
1150 ret = vk->CreateImage(s->hwctx->act_dev, &create_info,
1151 s->hwctx->alloc, img);
1152 if (ret != VK_SUCCESS) {
1153 av_log(s, AV_LOG_ERROR16, "Image creation failure: %s\n",
1154 ff_vk_ret2str(ret));
1155 return AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
1156 }
1157
1158 req_desc.image = *img;
1159 vk->GetImageMemoryRequirements2(s->hwctx->act_dev, &req_desc, &req);
1160
1161 /* Never shared with another image, so always dedicated */
1162 ded_alloc.image = *img;
1163 err = ff_vk_alloc_mem(s, &req.memoryRequirements,
1164 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
1165 &ded_alloc, &mem_flags, mem);
1166 if (err < 0)
1167 goto fail;
1168
1169 bind_info.image = *img;
1170 bind_info.memory = *mem;
1171 ret = vk->BindImageMemory2(s->hwctx->act_dev, 1, &bind_info);
1172 if (ret != VK_SUCCESS) {
1173 av_log(s, AV_LOG_ERROR16, "Failed to bind image memory: %s\n",
1174 ff_vk_ret2str(ret));
1175 err = AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
1176 goto fail;
1177 }
1178
1179 return 0;
1180
1181fail:
1182 ff_vk_image_free(s, img, mem);
1183 return err;
1184}
1185
1186void ff_vk_image_free(FFVulkanContext *s, VkImage *img, VkDeviceMemory *mem)
1187{
1188 FFVulkanFunctions *vk = &s->vkfn;
1189
1190 if (*img) {
1191 vk->DestroyImage(s->hwctx->act_dev, *img, s->hwctx->alloc);
1192 *img = VK_NULL_HANDLE((void*)0);
1193 }
1194 if (*mem) {
1195 vk->FreeMemory(s->hwctx->act_dev, *mem, s->hwctx->alloc);
1196 *mem = VK_NULL_HANDLE((void*)0);
1197 }
1198}
1199
1200int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size,
1201 void *pNext, void *alloc_pNext,
1202 VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags)
1203{
1204 int err;
1205 VkResult ret;
1206 int use_ded_mem;
1207 FFVulkanFunctions *vk = &s->vkfn;
1208
1209 VkBufferCreateInfo buf_spawn = {
1210 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1211 .pNext = pNext,
1212 .usage = usage,
1213 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
1214 .size = flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT ?
1215 FFALIGN(size, s->props.properties.limits.minMemoryMapAlignment)(((size)+(s->props.properties.limits.minMemoryMapAlignment
)-1)&~((s->props.properties.limits.minMemoryMapAlignment
)-1))
:
1216 size,
1217 };
1218
1219 VkMemoryAllocateFlagsInfo alloc_flags = {
1220 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
1221 .flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT,
1222 };
1223 VkBufferMemoryRequirementsInfo2 req_desc = {
1224 .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
1225 };
1226 VkMemoryDedicatedAllocateInfo ded_alloc = {
1227 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
1228 .pNext = alloc_pNext,
1229 };
1230 VkMemoryDedicatedRequirements ded_req = {
1231 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
1232 };
1233 VkMemoryRequirements2 req = {
1234 .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
1235 .pNext = &ded_req,
1236 };
1237
1238 av_log(s, AV_LOG_DEBUG48, "Creating a buffer of %zu bytes, "
1239 "usage: 0x%x, flags: 0x%x\n",
1240 size, usage, flags);
1241
1242 ret = vk->CreateBuffer(s->hwctx->act_dev, &buf_spawn, s->hwctx->alloc, &buf->buf);
1243 if (ret != VK_SUCCESS) {
1244 av_log(s, AV_LOG_ERROR16, "Failed to create buffer: %s\n",
1245 ff_vk_ret2str(ret));
1246 return AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
1247 }
1248
1249 req_desc.buffer = buf->buf;
1250
1251 vk->GetBufferMemoryRequirements2(s->hwctx->act_dev, &req_desc, &req);
1252
1253 /* In case the implementation prefers/requires dedicated allocation */
1254 use_ded_mem = ded_req.prefersDedicatedAllocation |
1255 ded_req.requiresDedicatedAllocation;
1256 if (use_ded_mem) {
1257 ded_alloc.buffer = buf->buf;
1258 ded_alloc.pNext = alloc_pNext;
1259 alloc_pNext = &ded_alloc;
1260 }
1261
1262 if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
1263 alloc_flags.pNext = alloc_pNext;
1264 alloc_pNext = &alloc_flags;
1265 }
1266
1267 err = ff_vk_alloc_mem(s, &req.memoryRequirements, flags, alloc_pNext,
1268 &buf->flags, &buf->mem);
1269 if (err)
1270 return err;
1271
1272 ret = vk->BindBufferMemory(s->hwctx->act_dev, buf->buf, buf->mem, 0);
1273 if (ret != VK_SUCCESS) {
1274 av_log(s, AV_LOG_ERROR16, "Failed to bind memory to buffer: %s\n",
1275 ff_vk_ret2str(ret));
1276 return AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
1277 }
1278
1279 if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
1280 VkBufferDeviceAddressInfo address_info = {
1281 .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
1282 .buffer = buf->buf,
1283 };
1284 buf->address = vk->GetBufferDeviceAddress(s->hwctx->act_dev, &address_info);
1285 }
1286
1287 buf->size = size;
1288
1289 return 0;
1290}
1291
1292int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer **buf, uint8_t *mem[],
1293 int nb_buffers, int invalidate)
1294{
1295 VkResult ret;
1296 FFVulkanFunctions *vk = &s->vkfn;
1297 VkMappedMemoryRange inval_list[64];
1298 int inval_count = 0;
1299
1300 for (int i = 0; i < nb_buffers; i++) {
1301 void *dst;
1302 ret = vk->MapMemory(s->hwctx->act_dev, buf[i]->mem, 0,
1303 VK_WHOLE_SIZE(~0ULL), 0, &dst);
1304 if (ret != VK_SUCCESS) {
1305 av_log(s, AV_LOG_ERROR16, "Failed to map buffer memory: %s\n",
1306 ff_vk_ret2str(ret));
1307 return AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
1308 }
1309 buf[i]->mapped_mem = dst;
1310 if (mem)
1311 mem[i] = dst;
1312 }
1313
1314 if (!invalidate)
1315 return 0;
1316
1317 for (int i = 0; i < nb_buffers; i++) {
1318 const VkMappedMemoryRange ival_buf = {
1319 .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
1320 .memory = buf[i]->mem,
1321 .size = VK_WHOLE_SIZE(~0ULL),
1322 };
1323 if (buf[i]->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
1324 continue;
1325 inval_list[inval_count++] = ival_buf;
1326 }
1327
1328 if (inval_count) {
1329 ret = vk->InvalidateMappedMemoryRanges(s->hwctx->act_dev, inval_count,
1330 inval_list);
1331 if (ret != VK_SUCCESS) {
1332 av_log(s, AV_LOG_ERROR16, "Failed to invalidate memory: %s\n",
1333 ff_vk_ret2str(ret));
1334 return AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
1335 }
1336 }
1337
1338 return 0;
1339}
1340
1341int ff_vk_flush_buffer(FFVulkanContext *s, FFVkBuffer *buf,
1342 VkDeviceSize offset, VkDeviceSize mem_size,
1343 int flush)
1344{
1345 VkResult ret;
1346 FFVulkanFunctions *vk = &s->vkfn;
1347
1348 if (buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
1349 return 0;
1350
1351 const VkMappedMemoryRange flush_data = {
1352 .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
1353 .memory = buf->mem,
1354 .offset = offset,
1355 .size = mem_size,
1356 };
1357
1358 if (flush)
1359 ret = vk->FlushMappedMemoryRanges(s->hwctx->act_dev, 1, &flush_data);
1360 else
1361 ret = vk->InvalidateMappedMemoryRanges(s->hwctx->act_dev, 1, &flush_data);
1362
1363 if (ret != VK_SUCCESS) {
1364 av_log(s, AV_LOG_ERROR16, "Failed to flush memory: %s\n",
1365 ff_vk_ret2str(ret));
1366 return AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
1367 }
1368
1369 return 0;
1370}
1371
1372int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer **buf, int nb_buffers,
1373 int flush)
1374{
1375 int err = 0;
1376 VkResult ret;
1377 FFVulkanFunctions *vk = &s->vkfn;
1378 VkMappedMemoryRange flush_list[64];
1379 int flush_count = 0;
1380
1381 if (flush) {
1382 for (int i = 0; i < nb_buffers; i++) {
1383 const VkMappedMemoryRange flush_buf = {
1384 .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
1385 .memory = buf[i]->mem,
1386 .size = VK_WHOLE_SIZE(~0ULL),
1387 };
1388
1389 av_assert0(!buf[i]->host_ref)do { if (!(!buf[i]->host_ref)) { av_log(((void*)0), 0, "Assertion %s failed at %s:%d\n"
, "!buf[i]->host_ref", "/root/firefox-clang/media/ffvpx/libavutil/vulkan.c"
, 1389); abort(); } } while (0)
;
1390 if (buf[i]->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
1391 continue;
1392 flush_list[flush_count++] = flush_buf;
1393 }
1394 }
1395
1396 if (flush_count) {
1397 ret = vk->FlushMappedMemoryRanges(s->hwctx->act_dev, flush_count,
1398 flush_list);
1399 if (ret != VK_SUCCESS) {
1400 av_log(s, AV_LOG_ERROR16, "Failed to flush memory: %s\n",
1401 ff_vk_ret2str(ret));
1402 err = AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
; /* We still want to try to unmap them */
1403 }
1404 }
1405
1406 for (int i = 0; i < nb_buffers; i++) {
1407 vk->UnmapMemory(s->hwctx->act_dev, buf[i]->mem);
1408 buf[i]->mapped_mem = NULL((void*)0);
1409 }
1410
1411 return err;
1412}
1413
1414void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf)
1415{
1416 FFVulkanFunctions *vk = &s->vkfn;
1417
1418 if (!buf || !s->hwctx)
1419 return;
1420
1421 if (buf->mapped_mem && !buf->host_ref)
1422 ff_vk_unmap_buffer(s, buf, 0);
1423 if (buf->buf != VK_NULL_HANDLE((void*)0))
1424 vk->DestroyBuffer(s->hwctx->act_dev, buf->buf, s->hwctx->alloc);
1425 if (buf->mem != VK_NULL_HANDLE((void*)0))
1426 vk->FreeMemory(s->hwctx->act_dev, buf->mem, s->hwctx->alloc);
1427 if (buf->host_ref)
1428 av_buffer_unref(&buf->host_ref);
1429
1430 buf->buf = VK_NULL_HANDLE((void*)0);
1431 buf->mem = VK_NULL_HANDLE((void*)0);
1432 buf->mapped_mem = NULL((void*)0);
1433}
1434
1435static void pooled_buf_free(AVRefStructOpaque opaque, void *obj)
1436{
1437 ff_vk_free_buf(opaque.nc, obj);
1438}
1439
1440int ff_vk_get_pooled_buffer(FFVulkanContext *ctx, AVRefStructPool **buf_pool,
1441 FFVkBuffer **buf, VkBufferUsageFlags usage,
1442 void *create_pNext, size_t size,
1443 VkMemoryPropertyFlagBits mem_props)
1444{
1445 int err;
1446 FFVkBuffer *data;
1447
1448 if (!(*buf_pool)) {
1449 *buf_pool = av_refstruct_pool_alloc_ext(sizeof(FFVkBuffer), 0, ctx,
1450 NULL((void*)0), NULL((void*)0), pooled_buf_free,
1451 NULL((void*)0));
1452 if (!(*buf_pool))
1453 return AVERROR(ENOMEM)(-(12));
1454 }
1455
1456 *buf = data = av_refstruct_pool_get(*buf_pool);
1457 if (!data)
1458 return AVERROR(ENOMEM)(-(12));
1459
1460 if (data->size >= size)
1461 return 0;
1462
1463 ff_vk_free_buf(ctx, data);
1464 memset(data, 0, sizeof(*data));
1465
1466 err = ff_vk_create_buf(ctx, data, size,
1467 create_pNext, NULL((void*)0), usage,
1468 mem_props);
1469 if (err < 0) {
1470 av_refstruct_unref(buf);
1471 return err;
1472 }
1473
1474 if (mem_props & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
1475 err = ff_vk_map_buffer(ctx, data, &data->mapped_mem, 0);
1476 if (err < 0) {
1477 av_refstruct_unref(buf);
1478 return err;
1479 }
1480 }
1481
1482 return 0;
1483}
1484
1485static int create_mapped_buffer(FFVulkanContext *s,
1486 FFVkBuffer *vkb, VkBufferUsageFlags usage,
1487 size_t size,
1488 VkExternalMemoryBufferCreateInfo *create_desc,
1489 VkImportMemoryHostPointerInfoEXT *import_desc,
1490 VkMemoryHostPointerPropertiesEXT props)
1491{
1492 int err;
1493 VkResult ret;
1494 FFVulkanFunctions *vk = &s->vkfn;
1495
1496 VkBufferCreateInfo buf_spawn = {
1497 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1498 .pNext = create_desc,
1499 .usage = usage,
1500 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
1501 .size = size,
1502 };
1503 VkMemoryRequirements req = {
1504 .size = size,
1505 .alignment = s->hprops.minImportedHostPointerAlignment,
1506 .memoryTypeBits = props.memoryTypeBits,
1507 };
1508
1509 err = ff_vk_alloc_mem(s, &req,
1510 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
1511 import_desc, &vkb->flags, &vkb->mem);
1512 if (err < 0)
1513 return err;
1514
1515 ret = vk->CreateBuffer(s->hwctx->act_dev, &buf_spawn, s->hwctx->alloc, &vkb->buf);
1516 if (ret != VK_SUCCESS) {
1517 vk->FreeMemory(s->hwctx->act_dev, vkb->mem, s->hwctx->alloc);
1518 return AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
1519 }
1520
1521 ret = vk->BindBufferMemory(s->hwctx->act_dev, vkb->buf, vkb->mem, 0);
1522 if (ret != VK_SUCCESS) {
1523 vk->FreeMemory(s->hwctx->act_dev, vkb->mem, s->hwctx->alloc);
1524 vk->DestroyBuffer(s->hwctx->act_dev, vkb->buf, s->hwctx->alloc);
1525 return AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
1526 }
1527
1528 return 0;
1529}
1530
1531static void host_map_free(AVRefStructOpaque opaque, void *obj)
1532{
1533 ff_vk_free_buf(opaque.nc, obj);
1534}
1535
1536int ff_vk_host_map_buffer(FFVulkanContext *s, FFVkBuffer **dst,
1537 uint8_t *src_data, VkDeviceSize size,
1538 const AVBufferRef *src_buf,
1539 VkBufferUsageFlags usage)
1540{
1541 int err;
1542 VkResult ret;
1543 FFVulkanFunctions *vk = &s->vkfn;
1544
1545 VkExternalMemoryBufferCreateInfo create_desc = {
1546 .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
1547 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,
1548 };
1549 VkMemoryAllocateFlagsInfo alloc_flags = {
1550 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
1551 .flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT,
1552 };
1553 VkImportMemoryHostPointerInfoEXT import_desc = {
1554 .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT,
1555 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,
1556 .pNext = usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT ? &alloc_flags : NULL((void*)0),
1557 };
1558 VkMemoryHostPointerPropertiesEXT props;
1559
1560 AVBufferRef *ref;
1561 FFVkBuffer *vkb;
1562 size_t offs;
1563 size_t buffer_size;
1564
1565 *dst = NULL((void*)0);
1566
1567 /* Get the previous point at which mapping was possible and use it */
1568 offs = (uintptr_t)src_data % s->hprops.minImportedHostPointerAlignment;
1569 import_desc.pHostPointer = src_data - offs;
1570
1571 props = (VkMemoryHostPointerPropertiesEXT) {
1572 VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT,
1573 };
1574 ret = vk->GetMemoryHostPointerPropertiesEXT(s->hwctx->act_dev,
1575 import_desc.handleType,
1576 import_desc.pHostPointer,
1577 &props);
1578 if (!(ret == VK_SUCCESS && props.memoryTypeBits))
1579 return AVERROR(EINVAL)(-(22));
1580
1581 /* Ref the source buffer */
1582 ref = av_buffer_ref(src_buf);
1583 if (!ref)
1584 return AVERROR(ENOMEM)(-(12));
1585
1586 /* Add the offset at the start, which gets ignored. */
1587 const VkDeviceSize src_avail = src_buf->size - (src_data - src_buf->data);
1588 buffer_size = offs + FFMIN(size, src_avail)((size) > (src_avail) ? (src_avail) : (size));
1589 buffer_size = FFALIGN(buffer_size, s->props.properties.limits.minMemoryMapAlignment)(((buffer_size)+(s->props.properties.limits.minMemoryMapAlignment
)-1)&~((s->props.properties.limits.minMemoryMapAlignment
)-1))
;
1590 buffer_size = FFALIGN(buffer_size, s->hprops.minImportedHostPointerAlignment)(((buffer_size)+(s->hprops.minImportedHostPointerAlignment
)-1)&~((s->hprops.minImportedHostPointerAlignment)-1))
;
1591
1592 /* Create a buffer struct */
1593 vkb = av_refstruct_alloc_ext(sizeof(*vkb), 0, s, host_map_free);
1594 if (!vkb) {
1595 av_buffer_unref(&ref);
1596 return AVERROR(ENOMEM)(-(12));
1597 }
1598
1599 err = create_mapped_buffer(s, vkb, usage,
1600 buffer_size, &create_desc, &import_desc,
1601 props);
1602 if (err < 0) {
1603 av_buffer_unref(&ref);
1604 av_refstruct_unref(&vkb);
1605 return err;
1606 }
1607
1608 if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
1609 VkBufferDeviceAddressInfo address_info = {
1610 .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
1611 .buffer = vkb->buf,
1612 };
1613 vkb->address = vk->GetBufferDeviceAddress(s->hwctx->act_dev, &address_info);
1614 }
1615
1616 vkb->host_ref = ref;
1617 vkb->virtual_offset = offs;
1618 vkb->address += offs;
1619 vkb->mapped_mem = src_data;
1620 vkb->size = buffer_size - offs;
1621
1622 *dst = vkb;
1623
1624 return 0;
1625}
1626
1627int ff_vk_shader_add_push_const(FFVulkanShader *shd, int offset, int size,
1628 VkShaderStageFlagBits stage)
1629{
1630 VkPushConstantRange *pc = &shd->push_consts[shd->push_consts_num++];
1631 av_assert1(shd->push_consts_num < FF_VK_MAX_PUSH_CONSTS)do { if (!(shd->push_consts_num < 4)) { av_log(((void*)
0), 0, "Assertion %s failed at %s:%d\n", "shd->push_consts_num < 4"
, "/root/firefox-clang/media/ffvpx/libavutil/vulkan.c", 1631)
; abort(); } } while (0)
;
1632 pc->stageFlags = stage;
1633 pc->offset = offset;
1634 pc->size = size;
1635 return 0;
1636}
1637
1638int ff_vk_init_sampler(FFVulkanContext *s, VkSampler *sampler,
1639 int unnorm_coords, VkFilter filt)
1640{
1641 VkResult ret;
1642 FFVulkanFunctions *vk = &s->vkfn;
1643
1644 VkSamplerCreateInfo sampler_info = {
1645 .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
1646 .magFilter = filt,
1647 .minFilter = sampler_info.magFilter,
1648 .mipmapMode = (unnorm_coords || filt == VK_FILTER_NEAREST) ?
1649 VK_SAMPLER_MIPMAP_MODE_NEAREST :
1650 VK_SAMPLER_MIPMAP_MODE_LINEAR,
1651 .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1652 .addressModeV = sampler_info.addressModeU,
1653 .addressModeW = sampler_info.addressModeU,
1654 .anisotropyEnable = VK_FALSE0U,
1655 .compareOp = VK_COMPARE_OP_NEVER,
1656 .borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
1657 .unnormalizedCoordinates = unnorm_coords,
1658 };
1659
1660 ret = vk->CreateSampler(s->hwctx->act_dev, &sampler_info,
1661 s->hwctx->alloc, sampler);
1662 if (ret != VK_SUCCESS) {
1663 av_log(s, AV_LOG_ERROR16, "Unable to init sampler: %s\n",
1664 ff_vk_ret2str(ret));
1665 return AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
1666 }
1667
1668 return 0;
1669}
1670
1671VkImageAspectFlags ff_vk_aspect_flag(AVFrame *f, int p)
1672{
1673 AVVkFrame *vkf = (AVVkFrame *)f->data[0];
1674 AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
1675 int nb_images = ff_vk_count_images(vkf);
1676 int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
1677
1678 static const VkImageAspectFlags plane_aspect[] = { VK_IMAGE_ASPECT_PLANE_0_BIT,
1679 VK_IMAGE_ASPECT_PLANE_1_BIT,
1680 VK_IMAGE_ASPECT_PLANE_2_BIT, };
1681
1682 if (ff_vk_mt_is_np_rgb(hwfc->sw_format) || (nb_planes == nb_images))
1683 return VK_IMAGE_ASPECT_COLOR_BIT;
1684
1685 return plane_aspect[p];
1686}
1687
1688int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt)
1689{
1690 if (pix_fmt == AV_PIX_FMT_ABGR || pix_fmt == AV_PIX_FMT_BGRA ||
1691 pix_fmt == AV_PIX_FMT_RGBA || pix_fmt == AV_PIX_FMT_RGB24 ||
1692 pix_fmt == AV_PIX_FMT_BGR24 || pix_fmt == AV_PIX_FMT_RGB48AV_PIX_FMT_RGB48LE ||
1693 pix_fmt == AV_PIX_FMT_RGBA64AV_PIX_FMT_RGBA64LE || pix_fmt == AV_PIX_FMT_RGB565AV_PIX_FMT_RGB565LE ||
1694 pix_fmt == AV_PIX_FMT_BGR565AV_PIX_FMT_BGR565LE || pix_fmt == AV_PIX_FMT_BGR0 ||
1695 pix_fmt == AV_PIX_FMT_0BGR || pix_fmt == AV_PIX_FMT_RGB0 ||
1696 pix_fmt == AV_PIX_FMT_GBRP10AV_PIX_FMT_GBRP10LE || pix_fmt == AV_PIX_FMT_GBRP12AV_PIX_FMT_GBRP12LE ||
1697 pix_fmt == AV_PIX_FMT_GBRP14AV_PIX_FMT_GBRP14LE || pix_fmt == AV_PIX_FMT_GBRP16AV_PIX_FMT_GBRP16LE ||
1698 pix_fmt == AV_PIX_FMT_GBRAP || pix_fmt == AV_PIX_FMT_GBRAP10AV_PIX_FMT_GBRAP10LE ||
1699 pix_fmt == AV_PIX_FMT_GBRAP12AV_PIX_FMT_GBRAP12LE || pix_fmt == AV_PIX_FMT_GBRAP14AV_PIX_FMT_GBRAP14LE ||
1700 pix_fmt == AV_PIX_FMT_GBRAP16AV_PIX_FMT_GBRAP16LE || pix_fmt == AV_PIX_FMT_GBRAP32AV_PIX_FMT_GBRAP32LE ||
1701 pix_fmt == AV_PIX_FMT_GBRPF16AV_PIX_FMT_GBRPF16LE || pix_fmt == AV_PIX_FMT_GBRAPF16AV_PIX_FMT_GBRAPF16LE ||
1702 pix_fmt == AV_PIX_FMT_GBRPF32AV_PIX_FMT_GBRPF32LE || pix_fmt == AV_PIX_FMT_GBRAPF32AV_PIX_FMT_GBRAPF32LE ||
1703 pix_fmt == AV_PIX_FMT_X2RGB10AV_PIX_FMT_X2RGB10LE || pix_fmt == AV_PIX_FMT_X2BGR10AV_PIX_FMT_X2BGR10LE ||
1704 pix_fmt == AV_PIX_FMT_RGBAF32AV_PIX_FMT_RGBAF32LE || pix_fmt == AV_PIX_FMT_RGBF32AV_PIX_FMT_RGBF32LE ||
1705 pix_fmt == AV_PIX_FMT_RGBA128AV_PIX_FMT_RGBA128LE || pix_fmt == AV_PIX_FMT_RGB96AV_PIX_FMT_RGB96LE ||
1706 pix_fmt == AV_PIX_FMT_GBRP || pix_fmt == AV_PIX_FMT_BAYER_RGGB16AV_PIX_FMT_BAYER_RGGB16LE)
1707 return 1;
1708 return 0;
1709}
1710
1711void ff_vk_set_perm(enum AVPixelFormat pix_fmt, int lut[4], int inv)
1712{
1713 switch (pix_fmt) {
1714 case AV_PIX_FMT_GBRP:
1715 case AV_PIX_FMT_GBRAP:
1716 case AV_PIX_FMT_GBRAP10AV_PIX_FMT_GBRAP10LE:
1717 case AV_PIX_FMT_GBRAP12AV_PIX_FMT_GBRAP12LE:
1718 case AV_PIX_FMT_GBRAP14AV_PIX_FMT_GBRAP14LE:
1719 case AV_PIX_FMT_GBRAP16AV_PIX_FMT_GBRAP16LE:
1720 case AV_PIX_FMT_GBRAPF16AV_PIX_FMT_GBRAPF16LE:
1721 case AV_PIX_FMT_GBRP10AV_PIX_FMT_GBRP10LE:
1722 case AV_PIX_FMT_GBRP12AV_PIX_FMT_GBRP12LE:
1723 case AV_PIX_FMT_GBRP14AV_PIX_FMT_GBRP14LE:
1724 case AV_PIX_FMT_GBRP16AV_PIX_FMT_GBRP16LE:
1725 case AV_PIX_FMT_GBRPF16AV_PIX_FMT_GBRPF16LE:
1726 case AV_PIX_FMT_GBRPF32AV_PIX_FMT_GBRPF32LE:
1727 case AV_PIX_FMT_GBRAP32AV_PIX_FMT_GBRAP32LE:
1728 case AV_PIX_FMT_GBRAPF32AV_PIX_FMT_GBRAPF32LE:
1729 lut[0] = 1;
1730 lut[1] = 2;
1731 lut[2] = 0;
1732 lut[3] = 3;
1733 break;
1734 case AV_PIX_FMT_X2BGR10AV_PIX_FMT_X2BGR10LE:
1735 lut[0] = 0;
1736 lut[1] = 2;
1737 lut[2] = 1;
1738 lut[3] = 3;
1739 break;
1740 case AV_PIX_FMT_BGRA:
1741 case AV_PIX_FMT_BGR0:
1742 /* Stored in RGBA images, so reverse them */
1743 lut[0] = 2;
1744 lut[1] = 1;
1745 lut[2] = 0;
1746 lut[3] = 3;
1747 break;
1748 default:
1749 lut[0] = 0;
1750 lut[1] = 1;
1751 lut[2] = 2;
1752 lut[3] = 3;
1753 break;
1754 }
1755
1756 if (inv) {
1757 int lut_tmp[4] = { lut[0], lut[1], lut[2], lut[3] };
1758 for (int i = 0; i < 4; i++)
1759 lut[lut_tmp[i]] = i;
1760 }
1761
1762 return;
1763}
1764
1765const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pix_fmt,
1766 enum FFVkShaderRepFormat rep_fmt)
1767{
1768 switch (pix_fmt) {
1769 case AV_PIX_FMT_RGBA:
1770 case AV_PIX_FMT_BGRA:
1771 case AV_PIX_FMT_RGB24:
1772 case AV_PIX_FMT_BGR24:
1773 case AV_PIX_FMT_BGR0:
1774 case AV_PIX_FMT_RGB0:
1775 case AV_PIX_FMT_RGB565AV_PIX_FMT_RGB565LE:
1776 case AV_PIX_FMT_BGR565AV_PIX_FMT_BGR565LE:
1777 case AV_PIX_FMT_UYVA:
1778 case AV_PIX_FMT_YUYV422:
1779 case AV_PIX_FMT_UYVY422: {
1780 const char *rep_tab[] = {
1781 [FF_VK_REP_NATIVE] = "rgba8ui",
1782 [FF_VK_REP_FLOAT] = "rgba8",
1783 [FF_VK_REP_INT] = "rgba8i",
1784 [FF_VK_REP_UINT] = "rgba8ui",
1785 };
1786 return rep_tab[rep_fmt];
1787 }
1788 case AV_PIX_FMT_X2RGB10AV_PIX_FMT_X2RGB10LE:
1789 case AV_PIX_FMT_X2BGR10AV_PIX_FMT_X2BGR10LE:
1790 case AV_PIX_FMT_Y210AV_PIX_FMT_Y210LE:
1791 case AV_PIX_FMT_XV30AV_PIX_FMT_XV30LE: {
1792 const char *rep_tab[] = {
1793 [FF_VK_REP_NATIVE] = "rgb10_a2ui",
1794 [FF_VK_REP_FLOAT] = "rgb10_a2",
1795 [FF_VK_REP_INT] = NULL((void*)0),
1796 [FF_VK_REP_UINT] = "rgb10_a2ui",
1797 };
1798 return rep_tab[rep_fmt];
1799 }
1800 case AV_PIX_FMT_RGB48AV_PIX_FMT_RGB48LE:
1801 case AV_PIX_FMT_RGBA64AV_PIX_FMT_RGBA64LE:
1802 case AV_PIX_FMT_Y212AV_PIX_FMT_Y212LE:
1803 case AV_PIX_FMT_Y216AV_PIX_FMT_Y216LE:
1804 case AV_PIX_FMT_XV36AV_PIX_FMT_XV36LE:
1805 case AV_PIX_FMT_XV48AV_PIX_FMT_XV48LE: {
1806 const char *rep_tab[] = {
1807 [FF_VK_REP_NATIVE] = "rgba16ui",
1808 [FF_VK_REP_FLOAT] = "rgba16",
1809 [FF_VK_REP_INT] = "rgba16i",
1810 [FF_VK_REP_UINT] = "rgba16ui",
1811 };
1812 return rep_tab[rep_fmt];
1813 }
1814 case AV_PIX_FMT_RGBAF16AV_PIX_FMT_RGBAF16LE: {
1815 const char *rep_tab[] = {
1816 [FF_VK_REP_NATIVE] = "rgba16f",
1817 [FF_VK_REP_FLOAT] = "rgba16f",
1818 [FF_VK_REP_INT] = "rgba32i",
1819 [FF_VK_REP_UINT] = "rgba16u",
1820 };
1821 return rep_tab[rep_fmt];
1822 }
1823 case AV_PIX_FMT_RGBF32AV_PIX_FMT_RGBF32LE:
1824 case AV_PIX_FMT_RGBAF32AV_PIX_FMT_RGBAF32LE: {
1825 const char *rep_tab[] = {
1826 [FF_VK_REP_NATIVE] = "rgba32f",
1827 [FF_VK_REP_FLOAT] = "rgba32f",
1828 [FF_VK_REP_INT] = "rgba32i",
1829 [FF_VK_REP_UINT] = "rgba32ui",
1830 };
1831 return rep_tab[rep_fmt];
1832 }
1833 case AV_PIX_FMT_RGB96AV_PIX_FMT_RGB96LE:
1834 case AV_PIX_FMT_RGBA128AV_PIX_FMT_RGBA128LE: {
1835 const char *rep_tab[] = {
1836 [FF_VK_REP_NATIVE] = "rgba32ui",
1837 [FF_VK_REP_FLOAT] = NULL((void*)0),
1838 [FF_VK_REP_INT] = "rgba32i",
1839 [FF_VK_REP_UINT] = "rgba32ui",
1840 };
1841 return rep_tab[rep_fmt];
1842 }
1843 case AV_PIX_FMT_GBRP:
1844 case AV_PIX_FMT_GRAY8:
1845 case AV_PIX_FMT_GBRAP:
1846 case AV_PIX_FMT_YUV420P:
1847 case AV_PIX_FMT_YUV422P:
1848 case AV_PIX_FMT_YUV444P:
1849 case AV_PIX_FMT_YUVA420P:
1850 case AV_PIX_FMT_YUVA422P:
1851 case AV_PIX_FMT_YUVA444P: {
1852 const char *rep_tab[] = {
1853 [FF_VK_REP_NATIVE] = "r8ui",
1854 [FF_VK_REP_FLOAT] = "r8",
1855 [FF_VK_REP_INT] = "r8i",
1856 [FF_VK_REP_UINT] = "r8ui",
1857 };
1858 return rep_tab[rep_fmt];
1859 };
1860 case AV_PIX_FMT_GRAY10AV_PIX_FMT_GRAY10LE:
1861 case AV_PIX_FMT_GRAY12AV_PIX_FMT_GRAY12LE:
1862 case AV_PIX_FMT_GRAY14AV_PIX_FMT_GRAY14LE:
1863 case AV_PIX_FMT_GRAY16AV_PIX_FMT_GRAY16LE:
1864 case AV_PIX_FMT_GBRAP10AV_PIX_FMT_GBRAP10LE:
1865 case AV_PIX_FMT_GBRAP12AV_PIX_FMT_GBRAP12LE:
1866 case AV_PIX_FMT_GBRAP14AV_PIX_FMT_GBRAP14LE:
1867 case AV_PIX_FMT_GBRAP16AV_PIX_FMT_GBRAP16LE:
1868 case AV_PIX_FMT_GBRAPF16AV_PIX_FMT_GBRAPF16LE:
1869 case AV_PIX_FMT_GBRP10AV_PIX_FMT_GBRP10LE:
1870 case AV_PIX_FMT_GBRP12AV_PIX_FMT_GBRP12LE:
1871 case AV_PIX_FMT_GBRP14AV_PIX_FMT_GBRP14LE:
1872 case AV_PIX_FMT_GBRP16AV_PIX_FMT_GBRP16LE:
1873 case AV_PIX_FMT_GBRPF16AV_PIX_FMT_GBRPF16LE:
1874 case AV_PIX_FMT_YUV420P10AV_PIX_FMT_YUV420P10LE:
1875 case AV_PIX_FMT_YUV420P12AV_PIX_FMT_YUV420P12LE:
1876 case AV_PIX_FMT_YUV420P16AV_PIX_FMT_YUV420P16LE:
1877 case AV_PIX_FMT_YUV422P10AV_PIX_FMT_YUV422P10LE:
1878 case AV_PIX_FMT_YUV422P12AV_PIX_FMT_YUV422P12LE:
1879 case AV_PIX_FMT_YUV422P16AV_PIX_FMT_YUV422P16LE:
1880 case AV_PIX_FMT_YUV444P10AV_PIX_FMT_YUV444P10LE:
1881 case AV_PIX_FMT_YUV444P12AV_PIX_FMT_YUV444P12LE:
1882 case AV_PIX_FMT_YUV444P16AV_PIX_FMT_YUV444P16LE:
1883 case AV_PIX_FMT_YUVA420P10AV_PIX_FMT_YUVA420P10LE:
1884 case AV_PIX_FMT_YUVA420P16AV_PIX_FMT_YUVA420P16LE:
1885 case AV_PIX_FMT_YUVA422P10AV_PIX_FMT_YUVA422P10LE:
1886 case AV_PIX_FMT_YUVA422P12AV_PIX_FMT_YUVA422P12LE:
1887 case AV_PIX_FMT_YUVA422P16AV_PIX_FMT_YUVA422P16LE:
1888 case AV_PIX_FMT_YUVA444P10AV_PIX_FMT_YUVA444P10LE:
1889 case AV_PIX_FMT_YUVA444P12AV_PIX_FMT_YUVA444P12LE:
1890 case AV_PIX_FMT_YUVA444P16AV_PIX_FMT_YUVA444P16LE:
1891 case AV_PIX_FMT_BAYER_RGGB16AV_PIX_FMT_BAYER_RGGB16LE: {
1892 const char *rep_tab[] = {
1893 [FF_VK_REP_NATIVE] = "r16ui",
1894 [FF_VK_REP_FLOAT] = "r16f",
1895 [FF_VK_REP_INT] = "r16i",
1896 [FF_VK_REP_UINT] = "r16ui",
1897 };
1898 return rep_tab[rep_fmt];
1899 };
1900 case AV_PIX_FMT_GRAY32AV_PIX_FMT_GRAY32LE:
1901 case AV_PIX_FMT_GRAYF32AV_PIX_FMT_GRAYF32LE:
1902 case AV_PIX_FMT_GBRPF32AV_PIX_FMT_GBRPF32LE:
1903 case AV_PIX_FMT_GBRAPF32AV_PIX_FMT_GBRAPF32LE: {
1904 const char *rep_tab[] = {
1905 [FF_VK_REP_NATIVE] = "r32f",
1906 [FF_VK_REP_FLOAT] = "r32f",
1907 [FF_VK_REP_INT] = "r32i",
1908 [FF_VK_REP_UINT] = "r32ui",
1909 };
1910 return rep_tab[rep_fmt];
1911 };
1912 case AV_PIX_FMT_GBRAP32AV_PIX_FMT_GBRAP32LE: {
1913 const char *rep_tab[] = {
1914 [FF_VK_REP_NATIVE] = "r32ui",
1915 [FF_VK_REP_FLOAT] = NULL((void*)0),
1916 [FF_VK_REP_INT] = "r32i",
1917 [FF_VK_REP_UINT] = "r32ui",
1918 };
1919 return rep_tab[rep_fmt];
1920 };
1921 case AV_PIX_FMT_NV12:
1922 case AV_PIX_FMT_NV16:
1923 case AV_PIX_FMT_NV24: {
1924 const char *rep_tab[] = {
1925 [FF_VK_REP_NATIVE] = "rg8ui",
1926 [FF_VK_REP_FLOAT] = "rg8",
1927 [FF_VK_REP_INT] = "rg8i",
1928 [FF_VK_REP_UINT] = "rg8ui",
1929 };
1930 return rep_tab[rep_fmt];
1931 };
1932 case AV_PIX_FMT_P010AV_PIX_FMT_P010LE:
1933 case AV_PIX_FMT_P210AV_PIX_FMT_P210LE:
1934 case AV_PIX_FMT_P410AV_PIX_FMT_P410LE: {
1935 const char *rep_tab[] = {
1936 [FF_VK_REP_NATIVE] = "rgb10_a2ui",
1937 [FF_VK_REP_FLOAT] = "rgb10_a2",
1938 [FF_VK_REP_INT] = NULL((void*)0),
1939 [FF_VK_REP_UINT] = "rgb10_a2ui",
1940 };
1941 return rep_tab[rep_fmt];
1942 };
1943 case AV_PIX_FMT_P012AV_PIX_FMT_P012LE:
1944 case AV_PIX_FMT_P016AV_PIX_FMT_P016LE:
1945 case AV_PIX_FMT_P212AV_PIX_FMT_P212LE:
1946 case AV_PIX_FMT_P216AV_PIX_FMT_P216LE:
1947 case AV_PIX_FMT_P412AV_PIX_FMT_P412LE:
1948 case AV_PIX_FMT_P416AV_PIX_FMT_P416LE: {
1949 const char *rep_tab[] = {
1950 [FF_VK_REP_NATIVE] = "rg16ui",
1951 [FF_VK_REP_FLOAT] = "rg16",
1952 [FF_VK_REP_INT] = "rg16i",
1953 [FF_VK_REP_UINT] = "rg16ui",
1954 };
1955 return rep_tab[rep_fmt];
1956 };
1957 default:
1958 return "rgba32f";
1959 }
1960}
1961
1962static void reset_imageviews(AVRefStructOpaque unused, void *obj)
1963{
1964 FFVkImageViews *iv = obj;
1965
1966 for (int i = 0; i < iv->nb_views; i++) {
1967 if (iv->views[i])
1968 iv->destroy_image_view(iv->dev, iv->views[i], iv->alloc);
1969 }
1970
1971 memset(iv->views, 0, sizeof(iv->views));
1972}
1973
1974FFVkImageViews *ff_vk_imageviews_alloc(FFVulkanContext *s, int nb_views)
1975{
1976 FFVulkanFunctions *vk = &s->vkfn;
1977 FFVkImageViews *iv;
1978
1979 av_assert1(nb_views <= AV_NUM_DATA_POINTERS)do { if (!(nb_views <= 8)) { av_log(((void*)0), 0, "Assertion %s failed at %s:%d\n"
, "nb_views <= 8", "/root/firefox-clang/media/ffvpx/libavutil/vulkan.c"
, 1979); abort(); } } while (0)
;
1980
1981 iv = av_refstruct_pool_get(s->imageviews_pool);
1982 if (!iv)
1983 return NULL((void*)0);
1984
1985 iv->nb_views = nb_views;
1986 iv->dev = s->hwctx->act_dev;
1987 iv->alloc = s->hwctx->alloc;
1988 iv->destroy_image_view = vk->DestroyImageView;
1989
1990 return iv;
1991}
1992
1993static VkFormat map_fmt_to_rep(VkFormat fmt, enum FFVkShaderRepFormat rep_fmt)
1994{
1995#define REPS_FMT(fmt) \
1996 [FF_VK_REP_NATIVE] = fmt ## _UINT, \
1997 [FF_VK_REP_FLOAT] = fmt ## _UNORM, \
1998 [FF_VK_REP_INT] = fmt ## _SINT, \
1999 [FF_VK_REP_UINT] = fmt ## _UINT,
2000
2001#define REPS_FMT_PACK(fmt, num) \
2002 [FF_VK_REP_NATIVE] = fmt ## _UINT_PACK ## num, \
2003 [FF_VK_REP_FLOAT] = fmt ## _UNORM_PACK ## num, \
2004 [FF_VK_REP_INT] = fmt ## _SINT_PACK ## num, \
2005 [FF_VK_REP_UINT] = fmt ## _UINT_PACK ## num,
2006
2007 const VkFormat fmts_map[][4] = {
2008 { REPS_FMT_PACK(VK_FORMAT_A2B10G10R10, 32) },
2009 { REPS_FMT_PACK(VK_FORMAT_A2R10G10B10, 32) },
2010 {
2011 VK_FORMAT_B5G6R5_UNORM_PACK16,
2012 VK_FORMAT_B5G6R5_UNORM_PACK16,
2013 VK_FORMAT_UNDEFINED,
2014 VK_FORMAT_UNDEFINED,
2015 },
2016 {
2017 VK_FORMAT_R5G6B5_UNORM_PACK16,
2018 VK_FORMAT_R5G6B5_UNORM_PACK16,
2019 VK_FORMAT_UNDEFINED,
2020 VK_FORMAT_UNDEFINED,
2021 },
2022 { REPS_FMT(VK_FORMAT_B8G8R8) },
2023 { REPS_FMT(VK_FORMAT_B8G8R8A8) },
2024 { REPS_FMT(VK_FORMAT_R8) },
2025 { REPS_FMT(VK_FORMAT_R8G8) },
2026 { REPS_FMT(VK_FORMAT_R8G8B8) },
2027 { REPS_FMT(VK_FORMAT_R8G8B8A8) },
2028 { REPS_FMT(VK_FORMAT_R16) },
2029 { REPS_FMT(VK_FORMAT_R16G16) },
2030 { REPS_FMT(VK_FORMAT_R16G16B16) },
2031 { REPS_FMT(VK_FORMAT_R16G16B16A16) },
2032 {
2033 VK_FORMAT_R32_UINT,
2034 VK_FORMAT_R32_SFLOAT,
2035 VK_FORMAT_R32_SINT,
2036 VK_FORMAT_R32_UINT,
2037 },
2038 {
2039 VK_FORMAT_R32G32B32_SFLOAT,
2040 VK_FORMAT_R32G32B32_SFLOAT,
2041 VK_FORMAT_UNDEFINED,
2042 VK_FORMAT_UNDEFINED,
2043 },
2044 {
2045 VK_FORMAT_R16G16B16A16_SFLOAT,
2046 VK_FORMAT_R16G16B16A16_SFLOAT,
2047 VK_FORMAT_UNDEFINED,
2048 VK_FORMAT_UNDEFINED,
2049 },
2050 {
2051 VK_FORMAT_R32G32B32A32_SFLOAT,
2052 VK_FORMAT_R32G32B32A32_SFLOAT,
2053 VK_FORMAT_UNDEFINED,
2054 VK_FORMAT_UNDEFINED,
2055 },
2056 {
2057 VK_FORMAT_R32G32B32_UINT,
2058 VK_FORMAT_UNDEFINED,
2059 VK_FORMAT_R32G32B32_SINT,
2060 VK_FORMAT_R32G32B32_UINT,
2061 },
2062 {
2063 VK_FORMAT_R32G32B32A32_UINT,
2064 VK_FORMAT_UNDEFINED,
2065 VK_FORMAT_R32G32B32A32_SINT,
2066 VK_FORMAT_R32G32B32A32_UINT,
2067 },
2068 {
2069 VK_FORMAT_R16_SFLOAT,
2070 VK_FORMAT_R16_SFLOAT,
2071 VK_FORMAT_R16_SINT,
2072 VK_FORMAT_R16_UINT,
2073 },
2074 };
2075#undef REPS_FMT_PACK
2076#undef REPS_FMT
2077
2078 if (fmt == VK_FORMAT_UNDEFINED)
2079 return VK_FORMAT_UNDEFINED;
2080
2081 for (int i = 0; i < FF_ARRAY_ELEMS(fmts_map)(sizeof(fmts_map) / sizeof((fmts_map)[0])); i++) {
2082 if (fmts_map[i][FF_VK_REP_NATIVE] == fmt ||
2083 fmts_map[i][FF_VK_REP_FLOAT] == fmt ||
2084 fmts_map[i][FF_VK_REP_INT] == fmt ||
2085 fmts_map[i][FF_VK_REP_UINT] == fmt)
2086 return fmts_map[i][rep_fmt];
2087 }
2088
2089 return VK_FORMAT_UNDEFINED;
2090}
2091
2092int ff_vk_create_imageview(FFVulkanContext *s,
2093 VkImageView *img_view, VkImageAspectFlags *aspect,
2094 AVFrame *f, int plane, enum FFVkShaderRepFormat rep_fmt)
2095{
2096 VkResult ret;
2097 FFVulkanFunctions *vk = &s->vkfn;
2098 AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
2099 AVVulkanFramesContext *vkfc = hwfc->hwctx;
2100 const VkFormat *rep_fmts = av_vkfmt_from_pixfmt(hwfc->sw_format);
2101 AVVkFrame *vkf = (AVVkFrame *)f->data[0];
2102 const int nb_images = ff_vk_count_images(vkf);
2103
2104 VkImageViewUsageCreateInfo view_usage_info = {
2105 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
2106 .usage = vkfc->usage &
2107 (~(VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR |
2108 VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR)),
2109 };
2110 VkImageViewCreateInfo view_create_info = {
2111 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
2112 .pNext = &view_usage_info,
2113 .image = vkf->img[FFMIN(plane, nb_images - 1)((plane) > (nb_images - 1) ? (nb_images - 1) : (plane))],
2114 .viewType = VK_IMAGE_VIEW_TYPE_2D,
2115 .format = map_fmt_to_rep(rep_fmts[plane], rep_fmt),
2116 .components = ff_comp_identity_map,
2117 .subresourceRange = {
2118 .aspectMask = ff_vk_aspect_flag(f, plane),
2119 .levelCount = 1,
2120 .layerCount = 1,
2121 },
2122 };
2123 if (view_create_info.format == VK_FORMAT_UNDEFINED) {
2124 av_log(s, AV_LOG_ERROR16, "Unable to find a compatible representation "
2125 "of format %i and mode %i\n",
2126 rep_fmts[plane], rep_fmt);
2127 return AVERROR(EINVAL)(-(22));
2128 }
2129
2130 ret = vk->CreateImageView(s->hwctx->act_dev, &view_create_info,
2131 s->hwctx->alloc, img_view);
2132 if (ret != VK_SUCCESS) {
2133 av_log(s, AV_LOG_ERROR16, "Failed to create imageview: %s\n",
2134 ff_vk_ret2str(ret));
2135 return AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
2136 }
2137
2138 *aspect = view_create_info.subresourceRange.aspectMask;
2139
2140 return 0;
2141}
2142
2143int ff_vk_create_imageviews(FFVulkanContext *s, FFVkExecContext *e,
2144 VkImageView views[AV_NUM_DATA_POINTERS8],
2145 AVFrame *f, enum FFVkShaderRepFormat rep_fmt)
2146{
2147 int err = 0;
2148 VkResult ret;
2149 FFVulkanFunctions *vk = &s->vkfn;
2150 AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
2151 AVVulkanFramesContext *vkfc = hwfc->hwctx;
2152 const VkFormat *rep_fmts = av_vkfmt_from_pixfmt(hwfc->sw_format);
2153 AVVkFrame *vkf = (AVVkFrame *)f->data[0];
2154 const int nb_images = ff_vk_count_images(vkf);
2155 const int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
2156 VkImageView tmp_views[AV_NUM_DATA_POINTERS8] = { 0 };
2157
2158 for (int i = 0; i < nb_planes; i++) {
2159 VkImageViewUsageCreateInfo view_usage_info = {
2160 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
2161 .usage = vkfc->usage &
2162 (~(VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR |
2163 VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR)),
2164 };
2165 VkImageViewCreateInfo view_create_info = {
2166 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
2167 .pNext = &view_usage_info,
2168 .image = vkf->img[FFMIN(i, nb_images - 1)((i) > (nb_images - 1) ? (nb_images - 1) : (i))],
2169 .viewType = VK_IMAGE_VIEW_TYPE_2D,
2170 .format = map_fmt_to_rep(rep_fmts[i], rep_fmt),
2171 .components = ff_comp_identity_map,
2172 .subresourceRange = {
2173 .aspectMask = ff_vk_aspect_flag(f, i),
2174 .levelCount = 1,
2175 .layerCount = 1,
2176 },
2177 };
2178 if (view_create_info.format == VK_FORMAT_UNDEFINED) {
2179 av_log(s, AV_LOG_ERROR16, "Unable to find a compatible representation "
2180 "of format %i and mode %i\n",
2181 rep_fmts[i], rep_fmt);
2182 err = AVERROR(EINVAL)(-(22));
2183 goto fail;
2184 }
2185
2186 ret = vk->CreateImageView(s->hwctx->act_dev, &view_create_info,
2187 s->hwctx->alloc, &tmp_views[i]);
2188 if (ret != VK_SUCCESS) {
2189 av_log(s, AV_LOG_ERROR16, "Failed to create imageview: %s\n",
2190 ff_vk_ret2str(ret));
2191 err = AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
2192 goto fail;
2193 }
2194 }
2195
2196 /* The execution context owns the views, destroying them on completion */
2197 for (int i = 0; i < nb_planes; i++)
2198 ff_vk_exec_add_dep_obj(s, e, VK_OBJECT_TYPE_IMAGE_VIEW,
2199 (uint64_t)tmp_views[i]);
2200
2201 memcpy(views, tmp_views, nb_planes*sizeof(*views));
2202
2203 return 0;
2204
2205fail:
2206 for (int i = 0; i < nb_planes; i++)
2207 if (tmp_views[i])
2208 vk->DestroyImageView(s->hwctx->act_dev, tmp_views[i], s->hwctx->alloc);
2209 return err;
2210}
2211
2212void ff_vk_frame_barrier(FFVulkanContext *s, FFVkExecContext *e,
2213 AVFrame *pic, VkImageMemoryBarrier2 *bar, int *nb_bar,
2214 VkPipelineStageFlags2 src_stage,
2215 VkPipelineStageFlags2 dst_stage,
2216 VkAccessFlagBits2 new_access,
2217 VkImageLayout new_layout,
2218 uint32_t new_qf)
2219{
2220 int found = -1;
2221 AVVkFrame *vkf = (AVVkFrame *)pic->data[0];
2222 const int nb_images = ff_vk_count_images(vkf);
2223 for (int i = 0; i < e->nb_frame_deps; i++)
2224 if (e->frame_deps[i]->data[0] == pic->data[0]) {
2225 if (e->frame_update[i])
2226 found = i;
2227 break;
2228 }
2229
2230 for (int i = 0; i < nb_images; i++) {
2231 bar[*nb_bar] = (VkImageMemoryBarrier2) {
2232 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
2233 .pNext = NULL((void*)0),
2234 .srcStageMask = src_stage,
2235 .dstStageMask = dst_stage,
2236 .srcAccessMask = found >= 0 ? e->access_dst[found] : vkf->access[i],
2237 .dstAccessMask = new_access,
2238 .oldLayout = found >= 0 ? e->layout_dst[found] : vkf->layout[0],
2239 .newLayout = new_layout,
2240 .srcQueueFamilyIndex = found >= 0 ? e->queue_family_dst[found] : vkf->queue_family[0],
2241 .dstQueueFamilyIndex = new_qf,
2242 .image = vkf->img[i],
2243 .subresourceRange = (VkImageSubresourceRange) {
2244 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
2245 .layerCount = 1,
2246 .levelCount = 1,
2247 },
2248 };
2249 *nb_bar += 1;
2250 }
2251
2252 ff_vk_exec_update_frame(s, e, pic, &bar[*nb_bar - nb_images], NULL((void*)0));
2253}
2254
2255int ff_vk_shader_load(FFVulkanShader *shd,
2256 VkPipelineStageFlags stage, VkSpecializationInfo *spec,
2257 uint32_t wg_size[3], uint32_t required_subgroup_size)
2258{
2259 shd->stage = stage;
2260 shd->precompiled = 1;
2261 shd->specialization_info = spec;
2262 memcpy(shd->lg_size, wg_size, 3*sizeof(uint32_t));
2263
2264 shd->subgroup_info = (VkPipelineShaderStageRequiredSubgroupSizeCreateInfo) {
2265 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO,
2266 .requiredSubgroupSize = required_subgroup_size,
2267 };
2268
2269 switch (shd->stage) {
2270 case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
2271 case VK_SHADER_STAGE_CALLABLE_BIT_KHR:
2272 case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
2273 case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
2274 case VK_SHADER_STAGE_MISS_BIT_KHR:
2275 case VK_SHADER_STAGE_RAYGEN_BIT_KHR:
2276 shd->bind_point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
2277 break;
2278 case VK_SHADER_STAGE_COMPUTE_BIT:
2279 shd->bind_point = VK_PIPELINE_BIND_POINT_COMPUTE;
2280 break;
2281 default:
2282 shd->bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS;
2283 break;
2284 };
2285
2286 return 0;
2287}
2288
2289static int init_pipeline_layout(FFVulkanContext *s, FFVulkanShader *shd)
2290{
2291 VkResult ret;
2292 FFVulkanFunctions *vk = &s->vkfn;
2293 VkPipelineLayoutCreateInfo pipeline_layout_info;
2294
2295 /* Finally create the pipeline layout */
2296 pipeline_layout_info = (VkPipelineLayoutCreateInfo) {
2297 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
2298 .pSetLayouts = shd->desc_layout,
2299 .setLayoutCount = shd->nb_descriptor_sets,
2300 .pushConstantRangeCount = shd->push_consts_num,
2301 .pPushConstantRanges = shd->push_consts,
2302 };
2303
2304 ret = vk->CreatePipelineLayout(s->hwctx->act_dev, &pipeline_layout_info,
2305 s->hwctx->alloc, &shd->pipeline_layout);
2306 if (ret != VK_SUCCESS) {
2307 av_log(s, AV_LOG_ERROR16, "Unable to init pipeline layout: %s\n",
2308 ff_vk_ret2str(ret));
2309 return AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
2310 }
2311
2312 return 0;
2313}
2314
2315static int create_shader_module(FFVulkanContext *s, FFVulkanShader *shd,
2316 VkShaderModule *mod,
2317 const uint8_t *spirv, size_t spirv_len)
2318{
2319 VkResult ret;
2320 FFVulkanFunctions *vk = &s->vkfn;
2321
2322 VkShaderModuleCreateInfo shader_module_info = {
2323 .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
2324 .pNext = NULL((void*)0),
2325 .flags = 0x0,
2326 .pCode = (void *)spirv,
2327 .codeSize = spirv_len,
2328 };
2329
2330 ret = vk->CreateShaderModule(s->hwctx->act_dev, &shader_module_info,
2331 s->hwctx->alloc, mod);
2332 if (ret != VK_SUCCESS) {
2333 av_log(s, AV_LOG_ERROR16, "Error creating shader module: %s\n",
2334 ff_vk_ret2str(ret));
2335 return AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
2336 }
2337
2338 return 0;
2339}
2340
2341static int init_compute_pipeline(FFVulkanContext *s, FFVulkanShader *shd,
2342 VkShaderModule mod, const char *entrypoint)
2343{
2344 VkResult ret;
2345 FFVulkanFunctions *vk = &s->vkfn;
2346
2347 VkComputePipelineCreateInfo pipeline_create_info = {
2348 .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
2349 .flags = 0x0,
2350 .layout = shd->pipeline_layout,
2351 .stage = (VkPipelineShaderStageCreateInfo) {
2352 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
2353 .pNext = shd->subgroup_info.requiredSubgroupSize ?
2354 &shd->subgroup_info : NULL((void*)0),
2355 .pName = entrypoint,
2356 .flags = shd->subgroup_info.requiredSubgroupSize ?
2357 VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT : 0x0,
2358 .stage = shd->stage,
2359 .module = mod,
2360 .pSpecializationInfo = shd->specialization_info,
2361 },
2362 };
2363
2364 ret = vk->CreateComputePipelines(s->hwctx->act_dev, VK_NULL_HANDLE((void*)0), 1,
2365 &pipeline_create_info,
2366 s->hwctx->alloc, &shd->pipeline);
2367 if (ret != VK_SUCCESS) {
2368 av_log(s, AV_LOG_ERROR16, "Unable to init compute pipeline: %s\n",
2369 ff_vk_ret2str(ret));
2370 return AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
2371 }
2372
2373 return 0;
2374}
2375
2376static int create_shader_object(FFVulkanContext *s, FFVulkanShader *shd,
2377 const uint8_t *spirv, size_t spirv_len,
2378 size_t *binary_size, const char *entrypoint)
2379{
2380 VkResult ret;
2381 FFVulkanFunctions *vk = &s->vkfn;
2382
2383 VkShaderCreateInfoEXT shader_obj_create = {
2384 .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,
2385 .pNext = shd->subgroup_info.requiredSubgroupSize ?
2386 &shd->subgroup_info : NULL((void*)0),
2387 .flags = shd->subgroup_info.requiredSubgroupSize ?
2388 VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT : 0x0,
2389 .stage = shd->stage,
2390 .nextStage = 0,
2391 .codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT,
2392 .pCode = spirv,
2393 .codeSize = spirv_len,
2394 .pName = entrypoint,
2395 .pSetLayouts = shd->desc_layout,
2396 .setLayoutCount = shd->nb_descriptor_sets,
2397 .pushConstantRangeCount = shd->push_consts_num,
2398 .pPushConstantRanges = shd->push_consts,
2399 .pSpecializationInfo = shd->specialization_info,
2400 };
2401
2402 ret = vk->CreateShadersEXT(s->hwctx->act_dev, 1, &shader_obj_create,
2403 s->hwctx->alloc, &shd->object);
2404 if (ret != VK_SUCCESS) {
2405 av_log(s, AV_LOG_ERROR16, "Unable to create shader object: %s\n",
2406 ff_vk_ret2str(ret));
2407 return AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
2408 }
2409
2410 if (vk->GetShaderBinaryDataEXT(s->hwctx->act_dev, shd->object,
2411 binary_size, NULL((void*)0)) != VK_SUCCESS)
2412 return AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
2413
2414 return 0;
2415}
2416
2417static int init_descriptors(FFVulkanContext *s, FFVulkanShader *shd)
2418{
2419 VkResult ret;
2420 FFVulkanFunctions *vk = &s->vkfn;
2421
2422 int has_singular = 0;
2423 int max_descriptors = 0;
2424 for (int i = 0; i < shd->nb_descriptor_sets; i++) {
2425 max_descriptors = FFMAX(max_descriptors, shd->desc_set[i].nb_bindings)((max_descriptors) > (shd->desc_set[i].nb_bindings) ? (
max_descriptors) : (shd->desc_set[i].nb_bindings))
;
2426 if (shd->desc_set[i].singular)
2427 has_singular = 1;
2428 }
2429 shd->use_push = (s->extensions & FF_VK_EXT_PUSH_DESCRIPTOR(1ULL << 14)) &&
2430 (max_descriptors <= s->push_desc_props.maxPushDescriptors) &&
2431 (shd->nb_descriptor_sets == 1) &&
2432 (has_singular == 0);
2433
2434 for (int i = 0; i < shd->nb_descriptor_sets; i++) {
2435 FFVulkanDescriptorSet *set = &shd->desc_set[i];
2436 VkDescriptorSetLayoutCreateInfo desc_layout_create = {
2437 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
2438 .bindingCount = set->nb_bindings,
2439 .pBindings = set->binding,
2440 .flags = (shd->use_push) ?
2441 VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR :
2442 0x0,
2443 };
2444
2445 ret = vk->CreateDescriptorSetLayout(s->hwctx->act_dev,
2446 &desc_layout_create,
2447 s->hwctx->alloc,
2448 &shd->desc_layout[i]);
2449 if (ret != VK_SUCCESS) {
2450 av_log(s, AV_LOG_ERROR16, "Unable to create descriptor set layout: %s",
2451 ff_vk_ret2str(ret));
2452 return AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
2453 }
2454 }
2455
2456 return 0;
2457}
2458
2459int ff_vk_shader_link(FFVulkanContext *s, FFVulkanShader *shd,
2460 const char *spirv, size_t spirv_len,
2461 const char *entrypoint)
2462{
2463 int err;
2464 FFVulkanFunctions *vk = &s->vkfn;
2465 VkSpecializationMapEntry spec_entries[3];
2466 VkSpecializationInfo spec_info;
2467 size_t input_size = spirv_len, binary_size = 0;
2468
2469 if (shd->precompiled) {
2470 if (!shd->specialization_info) {
2471 spec_info = (VkSpecializationInfo) {
2472 .pMapEntries = spec_entries,
2473 .mapEntryCount = 0,
2474 .pData = shd->lg_size,
2475 .dataSize = 0,
2476 };
2477 shd->specialization_info = &spec_info;
2478 }
2479
2480 VkSpecializationMapEntry *spe = (void *)shd->specialization_info->pMapEntries;
2481 for (int i = 0; i < 3; i++) {
2482 spe[shd->specialization_info->mapEntryCount++] = (VkSpecializationMapEntry) {
2483 .constantID = 253 + i,
2484 .offset = shd->specialization_info->dataSize + i*sizeof(uint32_t),
2485 .size = sizeof(uint32_t),
2486 };
2487 }
2488
2489 uint8_t *spd = (uint8_t *)shd->specialization_info->pData;
2490 memcpy(&spd[shd->specialization_info->dataSize],
2491 shd->lg_size, 3*sizeof(uint32_t));
2492 shd->specialization_info->dataSize += 3*sizeof(uint32_t);
2493
2494#if CONFIG_SHADER_COMPRESSION0
2495 uint8_t *out;
2496 size_t out_len;
2497 int ret = ff_zlib_expand(s, &out, &out_len, spirv, spirv_len);
2498 if (ret < 0)
2499 return ret;
2500 spirv = out;
2501 spirv_len = out_len;
2502#endif
2503 }
2504
2505 err = init_descriptors(s, shd);
2506 if (err < 0)
2507 goto end;
2508
2509 err = init_pipeline_layout(s, shd);
2510 if (err < 0)
2511 goto end;
2512
2513 if (s->extensions & FF_VK_EXT_SHADER_OBJECT(1ULL << 13)) {
2514 err = create_shader_object(s, shd, spirv, spirv_len,
2515 &binary_size, entrypoint);
2516 if (err < 0)
2517 goto end;
2518 } else {
2519 VkShaderModule mod;
2520 err = create_shader_module(s, shd, &mod, spirv, spirv_len);
2521 if (err < 0)
2522 goto end;
2523
2524 switch (shd->bind_point) {
2525 case VK_PIPELINE_BIND_POINT_COMPUTE:
2526 err = init_compute_pipeline(s, shd, mod, entrypoint);
2527 break;
2528 default:
2529 av_log(s, AV_LOG_ERROR16, "Unsupported shader type: %i\n",
2530 shd->bind_point);
2531 err = AVERROR(EINVAL)(-(22));
2532 goto end;
2533 break;
2534 };
2535
2536 vk->DestroyShaderModule(s->hwctx->act_dev, mod, s->hwctx->alloc);
2537 if (err < 0)
2538 goto end;
2539 }
2540
2541 if (shd->name)
2542 av_log(s, AV_LOG_VERBOSE40, "Shader %s linked, size:", shd->name);
2543 else
2544 av_log(s, AV_LOG_VERBOSE40, "Shader linked, size:");
2545
2546 if (input_size != spirv_len)
2547 av_log(s, AV_LOG_VERBOSE40, " %zu compressed,", input_size);
2548 av_log(s, AV_LOG_VERBOSE40, " %zu SPIR-V", spirv_len);
2549 if (binary_size != spirv_len)
2550 av_log(s, AV_LOG_VERBOSE40, ", %zu binary", binary_size);
2551 av_log(s, AV_LOG_VERBOSE40, "\n");
2552
2553end:
2554 if (shd->precompiled) {
2555 shd->specialization_info->mapEntryCount -= 3;
2556 shd->specialization_info->dataSize -= 3*sizeof(uint32_t);
2557 }
2558#if CONFIG_SHADER_COMPRESSION0
2559 if (shd->precompiled)
2560 av_free((void *)spirv);
2561#endif
2562 return err;
2563}
2564
2565void ff_vk_shader_add_descriptor_set(FFVulkanContext *s, FFVulkanShader *shd,
2566 const FFVulkanDescriptorSetBinding *desc, int nb,
2567 int singular)
2568{
2569 FFVulkanDescriptorSet *set = &shd->desc_set[shd->nb_descriptor_sets++];
2570 av_assert1(shd->nb_descriptor_sets < FF_VK_MAX_DESCRIPTOR_SETS)do { if (!(shd->nb_descriptor_sets < 4)) { av_log(((void
*)0), 0, "Assertion %s failed at %s:%d\n", "shd->nb_descriptor_sets < 4"
, "/root/firefox-clang/media/ffvpx/libavutil/vulkan.c", 2570)
; abort(); } } while (0)
;
2571 av_assert1(nb < FF_VK_MAX_DESCRIPTOR_BINDINGS)do { if (!(nb < 16)) { av_log(((void*)0), 0, "Assertion %s failed at %s:%d\n"
, "nb < 16", "/root/firefox-clang/media/ffvpx/libavutil/vulkan.c"
, 2571); abort(); } } while (0)
;
2572
2573 for (int i = 0; i < nb; i++) {
2574 set->binding[i].binding = i;
2575 set->binding[i].descriptorType = desc[i].type;
2576 set->binding[i].descriptorCount = FFMAX(desc[i].elems, 1)((desc[i].elems) > (1) ? (desc[i].elems) : (1));
2577 set->binding[i].stageFlags = desc[i].stages;
2578 set->binding[i].pImmutableSamplers = desc[i].samplers;
2579 }
2580
2581 for (int i = 0; i < nb; i++) {
2582 int j;
2583 for (j = 0; j < shd->nb_desc_pool_size; j++)
2584 if (shd->desc_pool_size[j].type == desc[i].type)
2585 break;
2586 if (j >= shd->nb_desc_pool_size) {
2587 shd->nb_desc_pool_size++;
2588 av_assert1(shd->nb_desc_pool_size < FF_VK_MAX_DESCRIPTOR_TYPES)do { if (!(shd->nb_desc_pool_size < 16)) { av_log(((void
*)0), 0, "Assertion %s failed at %s:%d\n", "shd->nb_desc_pool_size < 16"
, "/root/firefox-clang/media/ffvpx/libavutil/vulkan.c", 2588)
; abort(); } } while (0)
;
2589 }
2590
2591 shd->desc_pool_size[j].type = desc[i].type;
2592 shd->desc_pool_size[j].descriptorCount += FFMAX(desc[i].elems, 1)((desc[i].elems) > (1) ? (desc[i].elems) : (1));
2593 }
2594
2595 set->singular = singular;
2596 set->nb_bindings = nb;
2597}
2598
2599int ff_vk_shader_register_exec(FFVulkanContext *s, FFVkExecPool *pool,
2600 FFVulkanShader *shd)
2601{
2602 if (!shd->nb_descriptor_sets)
2603 return 0;
2604
2605 FFVulkanShaderData *sd = &pool->reg_shd[pool->nb_reg_shd++];
2606 av_assert1(pool->nb_reg_shd < FF_VK_MAX_SHADERS)do { if (!(pool->nb_reg_shd < 16)) { av_log(((void*)0),
0, "Assertion %s failed at %s:%d\n", "pool->nb_reg_shd < 16"
, "/root/firefox-clang/media/ffvpx/libavutil/vulkan.c", 2606)
; abort(); } } while (0)
;
2607
2608 sd->shd = shd;
2609 sd->nb_descriptor_sets = shd->nb_descriptor_sets;
2610
2611 if (!shd->use_push) {
2612 VkResult ret;
2613 FFVulkanFunctions *vk = &s->vkfn;
2614 VkDescriptorSetLayout *tmp_layouts;
2615 VkDescriptorSetAllocateInfo set_alloc_info;
2616 VkDescriptorPoolCreateInfo pool_create_info;
2617
2618 for (int i = 0; i < shd->nb_desc_pool_size; i++)
2619 shd->desc_pool_size[i].descriptorCount *= pool->pool_size;
2620
2621 pool_create_info = (VkDescriptorPoolCreateInfo) {
2622 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
2623 .flags = 0,
2624 .pPoolSizes = shd->desc_pool_size,
2625 .poolSizeCount = shd->nb_desc_pool_size,
2626 .maxSets = sd->nb_descriptor_sets*pool->pool_size,
2627 };
2628
2629 ret = vk->CreateDescriptorPool(s->hwctx->act_dev, &pool_create_info,
2630 s->hwctx->alloc, &sd->desc_pool);
2631 if (ret != VK_SUCCESS) {
2632 av_log(s, AV_LOG_ERROR16, "Unable to create descriptor pool: %s\n",
2633 ff_vk_ret2str(ret));
2634 return AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
2635 }
2636
2637 tmp_layouts = av_malloc_array(pool_create_info.maxSets, sizeof(*tmp_layouts));
2638 if (!tmp_layouts)
2639 return AVERROR(ENOMEM)(-(12));
2640
2641 /* Colate each execution context's descriptor set layouts */
2642 for (int i = 0; i < pool->pool_size; i++)
2643 for (int j = 0; j < sd->nb_descriptor_sets; j++)
2644 tmp_layouts[i*sd->nb_descriptor_sets + j] = shd->desc_layout[j];
2645
2646 set_alloc_info = (VkDescriptorSetAllocateInfo) {
2647 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
2648 .descriptorPool = sd->desc_pool,
2649 .pSetLayouts = tmp_layouts,
2650 .descriptorSetCount = pool_create_info.maxSets,
2651 };
2652
2653 sd->desc_sets = av_malloc_array(pool_create_info.maxSets,
2654 sizeof(*tmp_layouts));
2655 if (!sd->desc_sets) {
2656 av_free(tmp_layouts);
2657 return AVERROR(ENOMEM)(-(12));
2658 }
2659 ret = vk->AllocateDescriptorSets(s->hwctx->act_dev, &set_alloc_info,
2660 sd->desc_sets);
2661 av_free(tmp_layouts);
2662 if (ret != VK_SUCCESS) {
2663 av_log(s, AV_LOG_ERROR16, "Unable to allocate descriptor set: %s\n",
2664 ff_vk_ret2str(ret));
2665 av_freep(&sd->desc_sets);
2666 return AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | ((
unsigned)(' ') << 24)))
;
2667 }
2668 }
2669
2670 return 0;
2671}
2672
2673static inline const FFVulkanShaderData *get_shd_data(FFVkExecContext *e,
2674 const FFVulkanShader *shd)
2675{
2676 for (int i = 0; i < e->parent->nb_reg_shd; i++)
2677 if (e->parent->reg_shd[i].shd == shd)
2678 return &e->parent->reg_shd[i];
2679 return NULL((void*)0);
2680}
2681
2682static inline void update_set_pool_write(FFVulkanContext *s, FFVkExecContext *e,
2683 FFVulkanShader *shd, int set,
2684 VkWriteDescriptorSet *write_info)
2685{
2686 FFVulkanFunctions *vk = &s->vkfn;
2687 FFVulkanDescriptorSet *desc_set = &shd->desc_set[set];
2688 const FFVulkanShaderData *sd = get_shd_data(e, shd);
2689
2690 if (desc_set->singular) {
2691 for (int i = 0; i < e->parent->pool_size; i++) {
2692 write_info->dstSet = sd->desc_sets[i*sd->nb_descriptor_sets + set];
2693 vk->UpdateDescriptorSets(s->hwctx->act_dev, 1, write_info, 0, NULL((void*)0));
2694 }
2695 } else {
2696 if (shd->use_push) {
2697 vk->CmdPushDescriptorSetKHR(e->buf,
2698 shd->bind_point,
2699 shd->pipeline_layout,
2700 set, 1,
2701 write_info);
2702 } else {
2703 write_info->dstSet = sd->desc_sets[e->idx*sd->nb_descriptor_sets + set];
2704 vk->UpdateDescriptorSets(s->hwctx->act_dev, 1, write_info, 0, NULL((void*)0));
2705 }
2706 }
2707}
2708
2709int ff_vk_shader_update_img(FFVulkanContext *s, FFVkExecContext *e,
2710 FFVulkanShader *shd, int set, int bind, int offs,
2711 VkImageView view, VkImageLayout layout,
2712 VkSampler sampler)
2713{
2714 FFVulkanDescriptorSet *desc_set = &shd->desc_set[set];
2715
2716 VkDescriptorImageInfo desc_pool_write_info_img = {
2717 .sampler = sampler,
2718 .imageView = view,
2719 .imageLayout = layout,
2720 };
2721 VkWriteDescriptorSet desc_pool_write_info = {
2722 .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
2723 .dstBinding = bind,
2724 .descriptorCount = 1,
2725 .dstArrayElement = offs,
2726 .descriptorType = desc_set->binding[bind].descriptorType,
2727 .pImageInfo = &desc_pool_write_info_img,
2728 };
2729 update_set_pool_write(s, e, shd, set, &desc_pool_write_info);
2730
2731 return 0;
2732}
2733
2734void ff_vk_shader_update_img_array(FFVulkanContext *s, FFVkExecContext *e,
2735 FFVulkanShader *shd, AVFrame *f,
2736 VkImageView *views, int set, int binding,
2737 VkImageLayout layout, VkSampler sampler)
2738{
2739 AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
2740 const int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
2741
2742 for (int i = 0; i < nb_planes; i++)
2743 ff_vk_shader_update_img(s, e, shd, set, binding, i,
2744 views[i], layout, sampler);
2745}
2746
2747int ff_vk_shader_update_desc_buffer(FFVulkanContext *s, FFVkExecContext *e,
2748 FFVulkanShader *shd,
2749 int set, int bind, int elem,
2750 FFVkBuffer *buf, VkDeviceSize offset, VkDeviceSize len,
2751 VkFormat fmt)
2752{
2753 FFVulkanDescriptorSet *desc_set = &shd->desc_set[set];
2754
2755 VkDescriptorBufferInfo desc_pool_write_info_buf = {
2756 .buffer = buf->buf,
2757 .offset = buf->virtual_offset + offset,
2758 .range = len,
2759 };
2760 VkWriteDescriptorSet desc_pool_write_info = {
2761 .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
2762 .dstBinding = bind,
2763 .descriptorCount = 1,
2764 .dstArrayElement = elem,
2765 .descriptorType = desc_set->binding[bind].descriptorType,
2766 .pBufferInfo = &desc_pool_write_info_buf,
2767 };
2768 update_set_pool_write(s, e, shd, set, &desc_pool_write_info);
2769
2770 return 0;
2771}
2772
2773void ff_vk_shader_update_push_const(FFVulkanContext *s, FFVkExecContext *e,
2774 FFVulkanShader *shd,
2775 VkShaderStageFlagBits stage,
2776 int offset, size_t size, void *src)
2777{
2778 FFVulkanFunctions *vk = &s->vkfn;
2779 vk->CmdPushConstants(e->buf, shd->pipeline_layout,
2780 stage, offset, size, src);
2781}
2782
2783void ff_vk_exec_bind_shader(FFVulkanContext *s, FFVkExecContext *e,
2784 const FFVulkanShader *shd)
2785{
2786 FFVulkanFunctions *vk = &s->vkfn;
2787 const FFVulkanShaderData *sd = get_shd_data(e, shd);
2788
2789 if (s->extensions & FF_VK_EXT_SHADER_OBJECT(1ULL << 13)) {
2790 VkShaderStageFlagBits stages = shd->stage;
2791 vk->CmdBindShadersEXT(e->buf, 1, &stages, &shd->object);
2792 } else {
2793 vk->CmdBindPipeline(e->buf, shd->bind_point, shd->pipeline);
2794 }
2795
2796 if (sd && sd->nb_descriptor_sets) {
2797 if (!shd->use_push) {
2798 vk->CmdBindDescriptorSets(e->buf, shd->bind_point, shd->pipeline_layout,
2799 0, sd->nb_descriptor_sets,
2800 &sd->desc_sets[e->idx*sd->nb_descriptor_sets],
2801 0, NULL((void*)0));
2802 }
2803 }
2804}
2805
2806void ff_vk_shader_free(FFVulkanContext *s, FFVulkanShader *shd)
2807{
2808 FFVulkanFunctions *vk = &s->vkfn;
2809
2810#if 0
2811 if (shd->shader.module)
2812 vk->DestroyShaderModule(s->hwctx->act_dev, shd->shader.module,
2813 s->hwctx->alloc);
2814#endif
2815
2816 if (shd->object)
2817 vk->DestroyShaderEXT(s->hwctx->act_dev, shd->object, s->hwctx->alloc);
2818 if (shd->pipeline)
2819 vk->DestroyPipeline(s->hwctx->act_dev, shd->pipeline, s->hwctx->alloc);
2820 if (shd->pipeline_layout)
2821 vk->DestroyPipelineLayout(s->hwctx->act_dev, shd->pipeline_layout,
2822 s->hwctx->alloc);
2823
2824 for (int i = 0; i < shd->nb_descriptor_sets; i++)
2825 if (shd->desc_layout[i])
2826 vk->DestroyDescriptorSetLayout(s->hwctx->act_dev, shd->desc_layout[i],
2827 s->hwctx->alloc);
2828}
2829
2830void ff_vk_uninit(FFVulkanContext *s)
2831{
2832 av_freep(&s->query_props);
2833 av_freep(&s->qf_props);
2834 av_freep(&s->video_props);
2835#ifdef VK_KHR_maintenance91
2836 av_freep(&s->ownership_props);
2837#endif
2838 av_freep(&s->coop_mat_props);
2839 av_freep(&s->host_image_copy_layouts);
2840 av_refstruct_pool_uninit(&s->imageviews_pool);
2841
2842 av_buffer_unref(&s->device_ref);
2843 av_buffer_unref(&s->frames_ref);
2844}
2845
2846int ff_vk_init(FFVulkanContext *s, void *log_parent,
2847 AVBufferRef *device_ref, AVBufferRef *frames_ref)
2848{
2849 int err;
2850
2851 static const AVClass vulkan_context_class = {
2852 .class_name = "vk",
2853 .version = LIBAVUTIL_VERSION_INT((61)<<16 | (1)<<8 | (101)),
2854 .parent_log_context_offset = offsetof(FFVulkanContext, log_parent)__builtin_offsetof(FFVulkanContext, log_parent),
2855 };
2856
2857 memset(s, 0, sizeof(*s));
2858 s->log_parent = log_parent;
2859 s->class = &vulkan_context_class;
2860
2861 if (frames_ref) {
2862 s->frames_ref = av_buffer_ref(frames_ref);
2863 if (!s->frames_ref)
2864 return AVERROR(ENOMEM)(-(12));
2865
2866 s->frames = (AVHWFramesContext *)s->frames_ref->data;
2867 s->hwfc = s->frames->hwctx;
2868
2869 device_ref = s->frames->device_ref;
2870 }
2871
2872 s->device_ref = av_buffer_ref(device_ref);
2873 if (!s->device_ref) {
2874 ff_vk_uninit(s);
2875 return AVERROR(ENOMEM)(-(12));
2876 }
2877
2878 s->device = (AVHWDeviceContext *)s->device_ref->data;
2879 s->hwctx = s->device->hwctx;
2880
2881 s->extensions = ff_vk_extensions_to_mask(s->hwctx->enabled_dev_extensions,
2882 s->hwctx->nb_enabled_dev_extensions);
2883 s->extensions |= ff_vk_extensions_to_mask(s->hwctx->enabled_inst_extensions,
2884 s->hwctx->nb_enabled_inst_extensions);
2885
2886 err = ff_vk_load_functions(s->device, &s->vkfn, s->extensions, 1, 1);
2887 if (err < 0) {
2888 ff_vk_uninit(s);
2889 return err;
2890 }
2891
2892 err = ff_vk_load_props(s);
2893 if (err < 0) {
2894 ff_vk_uninit(s);
2895 return err;
2896 }
2897
2898 return 0;
2899}