Bug Summary

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