30 #include <drm_fourcc.h> 33 #include <va/va_drmcommon.h> 41 #define CHECK_CU(x) FF_CUDA_CHECK_DL(cuda_cu, cu, x) 65 VkPhysicalDeviceProperties2
props;
66 VkPhysicalDeviceMemoryProperties
mprops;
67 VkPhysicalDeviceExternalMemoryHostPropertiesEXT
hprops;
107 #define GET_QUEUE_COUNT(hwctx, graph, comp, tx) ( \ 108 graph ? hwctx->nb_graphics_queues : \ 109 comp ? (hwctx->nb_comp_queues ? \ 110 hwctx->nb_comp_queues : hwctx->nb_graphics_queues) : \ 111 tx ? (hwctx->nb_tx_queues ? hwctx->nb_tx_queues : \ 112 (hwctx->nb_comp_queues ? \ 113 hwctx->nb_comp_queues : hwctx->nb_graphics_queues)) : \ 117 #define VK_LOAD_PFN(inst, name) PFN_##name pfn_##name = (PFN_##name) \ 118 vkGetInstanceProcAddr(inst, #name) 120 #define DEFAULT_USAGE_FLAGS (VK_IMAGE_USAGE_SAMPLED_BIT | \ 121 VK_IMAGE_USAGE_STORAGE_BIT | \ 122 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | \ 123 VK_IMAGE_USAGE_TRANSFER_DST_BIT) 125 #define ADD_VAL_TO_LIST(list, count, val) \ 127 list = av_realloc_array(list, sizeof(*list), ++count); \ 129 err = AVERROR(ENOMEM); \ 132 list[count - 1] = av_strdup(val); \ 133 if (!list[count - 1]) { \ 134 err = AVERROR(ENOMEM); \ 139 static const struct {
157 {
AV_PIX_FMT_YUV420P, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } },
162 {
AV_PIX_FMT_YUV422P, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } },
167 {
AV_PIX_FMT_YUV444P, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } },
172 {
AV_PIX_FMT_YUVA420P, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } },
173 {
AV_PIX_FMT_YUVA420P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
175 {
AV_PIX_FMT_YUVA420P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
177 {
AV_PIX_FMT_YUVA422P, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } },
178 {
AV_PIX_FMT_YUVA422P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
179 {
AV_PIX_FMT_YUVA422P12, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
180 {
AV_PIX_FMT_YUVA422P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
182 {
AV_PIX_FMT_YUVA444P, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } },
183 {
AV_PIX_FMT_YUVA444P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
184 {
AV_PIX_FMT_YUVA444P12, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
185 {
AV_PIX_FMT_YUVA444P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
206 {
AV_PIX_FMT_GBRAP, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } },
207 {
AV_PIX_FMT_GBRAP16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
208 {
AV_PIX_FMT_GBRPF32, { VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT } },
209 {
AV_PIX_FMT_GBRAPF32, { VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT } },
230 VkFormatFeatureFlags
flags;
231 VkFormatProperties2 prop = {
232 .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
234 vkGetPhysicalDeviceFormatProperties2(hwctx->
phys_dev, fmt[
i], &prop);
235 flags = linear ? prop.formatProperties.linearTilingFeatures :
236 prop.formatProperties.optimalTilingFeatures;
278 #define CASE(VAL) case VAL: return #VAL 284 CASE(VK_EVENT_RESET);
286 CASE(VK_ERROR_OUT_OF_HOST_MEMORY);
287 CASE(VK_ERROR_OUT_OF_DEVICE_MEMORY);
288 CASE(VK_ERROR_INITIALIZATION_FAILED);
289 CASE(VK_ERROR_DEVICE_LOST);
290 CASE(VK_ERROR_MEMORY_MAP_FAILED);
291 CASE(VK_ERROR_LAYER_NOT_PRESENT);
292 CASE(VK_ERROR_EXTENSION_NOT_PRESENT);
293 CASE(VK_ERROR_FEATURE_NOT_PRESENT);
294 CASE(VK_ERROR_INCOMPATIBLE_DRIVER);
295 CASE(VK_ERROR_TOO_MANY_OBJECTS);
296 CASE(VK_ERROR_FORMAT_NOT_SUPPORTED);
297 CASE(VK_ERROR_FRAGMENTED_POOL);
298 CASE(VK_ERROR_SURFACE_LOST_KHR);
299 CASE(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR);
300 CASE(VK_SUBOPTIMAL_KHR);
301 CASE(VK_ERROR_OUT_OF_DATE_KHR);
302 CASE(VK_ERROR_INCOMPATIBLE_DISPLAY_KHR);
303 CASE(VK_ERROR_VALIDATION_FAILED_EXT);
304 CASE(VK_ERROR_INVALID_SHADER_NV);
305 CASE(VK_ERROR_OUT_OF_POOL_MEMORY);
306 CASE(VK_ERROR_INVALID_EXTERNAL_HANDLE);
307 CASE(VK_ERROR_NOT_PERMITTED_EXT);
308 CASE(VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT);
309 CASE(VK_ERROR_INVALID_DEVICE_ADDRESS_EXT);
310 CASE(VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT);
311 default:
return "Unknown error";
317 VkDebugUtilsMessageTypeFlagsEXT messageType,
318 const VkDebugUtilsMessengerCallbackDataEXT *
data,
325 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: l =
AV_LOG_VERBOSE;
break;
326 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: l =
AV_LOG_INFO;
break;
327 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: l =
AV_LOG_WARNING;
break;
328 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: l =
AV_LOG_ERROR;
break;
332 av_log(ctx, l,
"%s\n", data->pMessage);
333 for (
int i = 0;
i < data->cmdBufLabelCount;
i++)
334 av_log(ctx, l,
"\t%i: %s\n",
i, data->pCmdBufLabels[
i].pLabelName);
340 const char *
const **dst, uint32_t *num,
int debug)
343 const char **extension_names =
NULL;
346 int err = 0, found, extensions_found = 0;
349 int optional_exts_num;
350 uint32_t sup_ext_count;
351 char *user_exts_str =
NULL;
353 VkExtensionProperties *sup_ext;
363 if (!user_exts_str) {
368 vkEnumerateInstanceExtensionProperties(
NULL, &sup_ext_count,
NULL);
369 sup_ext =
av_malloc_array(sup_ext_count,
sizeof(VkExtensionProperties));
372 vkEnumerateInstanceExtensionProperties(
NULL, &sup_ext_count, sup_ext);
380 if (!user_exts_str) {
385 vkEnumerateDeviceExtensionProperties(hwctx->
phys_dev,
NULL,
386 &sup_ext_count,
NULL);
387 sup_ext =
av_malloc_array(sup_ext_count,
sizeof(VkExtensionProperties));
390 vkEnumerateDeviceExtensionProperties(hwctx->
phys_dev,
NULL,
391 &sup_ext_count, sup_ext);
394 for (
int i = 0;
i < optional_exts_num;
i++) {
395 tstr = optional_exts[
i].
name;
397 for (
int j = 0; j < sup_ext_count; j++) {
398 if (!strcmp(tstr, sup_ext[j].extensionName)) {
412 tstr = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
414 for (
int j = 0; j < sup_ext_count; j++) {
415 if (!strcmp(tstr, sup_ext[j].extensionName)) {
432 char *save, *token =
av_strtok(user_exts_str,
"+", &save);
435 for (
int j = 0; j < sup_ext_count; j++) {
436 if (!strcmp(token, sup_ext[j].extensionName)) {
452 *dst = extension_names;
453 *num = extensions_found;
461 for (
int i = 0;
i < extensions_found;
i++)
462 av_free((
void *)extension_names[
i]);
477 const int debug_mode = debug_opt && strtol(debug_opt->
value,
NULL, 10);
478 VkApplicationInfo application_info = {
479 .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
480 .pEngineName =
"libavutil",
481 .apiVersion = VK_API_VERSION_1_1,
486 VkInstanceCreateInfo inst_props = {
487 .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
488 .pApplicationInfo = &application_info,
493 &inst_props.enabledExtensionCount, debug_mode);
498 static const char *layers[] = {
"VK_LAYER_KHRONOS_validation" };
499 inst_props.ppEnabledLayerNames = layers;
504 ret = vkCreateInstance(&inst_props, hwctx->
alloc, &hwctx->
inst);
507 if (ret != VK_SUCCESS) {
510 for (
int i = 0;
i < inst_props.enabledExtensionCount;
i++)
511 av_free((
void *)inst_props.ppEnabledExtensionNames[
i]);
512 av_free((
void *)inst_props.ppEnabledExtensionNames);
517 VkDebugUtilsMessengerCreateInfoEXT dbg = {
518 .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
519 .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
520 VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT |
521 VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
522 VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
523 .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
524 VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
525 VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
531 pfn_vkCreateDebugUtilsMessengerEXT(hwctx->
inst, &dbg,
553 case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
return "integrated";
554 case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
return "discrete";
555 case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
return "virtual";
556 case VK_PHYSICAL_DEVICE_TYPE_CPU:
return "software";
557 default:
return "unknown";
564 int err = 0, choice = -1;
567 VkPhysicalDevice *devices =
NULL;
568 VkPhysicalDeviceIDProperties *idp =
NULL;
569 VkPhysicalDeviceProperties2 *prop =
NULL;
572 ret = vkEnumeratePhysicalDevices(hwctx->
inst, &num,
NULL);
573 if (ret != VK_SUCCESS || !num) {
582 ret = vkEnumeratePhysicalDevices(hwctx->
inst, &num, devices);
583 if (ret != VK_SUCCESS) {
603 for (
int i = 0;
i < num;
i++) {
604 idp[
i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
605 prop[
i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
606 prop[
i].pNext = &idp[
i];
608 vkGetPhysicalDeviceProperties2(devices[
i], &prop[i]);
610 prop[i].properties.deviceName,
612 prop[i].properties.deviceID);
616 for (
int i = 0;
i < num;
i++) {
617 if (!strncmp(idp[
i].deviceUUID, select->
uuid, VK_UUID_SIZE)) {
625 }
else if (select->
name) {
627 for (
int i = 0;
i < num;
i++) {
628 if (strstr(prop[
i].properties.deviceName, select->
name)) {
639 for (
int i = 0;
i < num;
i++) {
640 if (select->
pci_device == prop[
i].properties.deviceID) {
651 for (
int i = 0;
i < num;
i++) {
652 if (select->
vendor_id == prop[
i].properties.vendorID) {
662 if (select->
index < num) {
663 choice = select->
index;
687 VkQueueFamilyProperties *qs =
NULL;
689 int graph_index = -1, comp_index = -1, tx_index = -1;
690 VkDeviceQueueCreateInfo *pc = (VkDeviceQueueCreateInfo *)cd->pQueueCreateInfos;
693 vkGetPhysicalDeviceQueueFamilyProperties(hwctx->
phys_dev, &num,
NULL);
705 vkGetPhysicalDeviceQueueFamilyProperties(hwctx->
phys_dev, &num, qs);
707 #define SEARCH_FLAGS(expr, out) \ 708 for (int i = 0; i < num; i++) { \ 709 const VkQueueFlagBits flags = qs[i].queueFlags; \ 722 (
i != comp_index), tx_index)
725 #define ADD_QUEUE(fidx, graph, comp, tx) \ 726 av_log(ctx, AV_LOG_VERBOSE, "Using queue family %i (total queues: %i) for %s%s%s\n", \ 727 fidx, qs[fidx].queueCount, graph ? "graphics " : "", \ 728 comp ? "compute " : "", tx ? "transfers " : ""); \ 729 av_log(ctx, AV_LOG_VERBOSE, " QF %i flags: %s%s%s%s\n", fidx, \ 730 ((qs[fidx].queueFlags) & VK_QUEUE_GRAPHICS_BIT) ? "(graphics) " : "", \ 731 ((qs[fidx].queueFlags) & VK_QUEUE_COMPUTE_BIT) ? "(compute) " : "", \ 732 ((qs[fidx].queueFlags) & VK_QUEUE_TRANSFER_BIT) ? "(transfers) " : "", \ 733 ((qs[fidx].queueFlags) & VK_QUEUE_SPARSE_BINDING_BIT) ? "(sparse) " : ""); \ 734 pc[cd->queueCreateInfoCount].queueFamilyIndex = fidx; \ 735 pc[cd->queueCreateInfoCount].queueCount = qs[fidx].queueCount; \ 736 weights = av_malloc(qs[fidx].queueCount * sizeof(float)); \ 737 pc[cd->queueCreateInfoCount].pQueuePriorities = weights; \ 740 for (int i = 0; i < qs[fidx].queueCount; i++) \ 742 cd->queueCreateInfoCount++; 744 ADD_QUEUE(graph_index, 1, comp_index < 0, tx_index < 0 && comp_index < 0)
750 if (comp_index != -1) {
751 ADD_QUEUE(comp_index, 0, 1, tx_index < 0)
757 if (tx_index != -1) {
778 int queue_family_index,
int num_queues)
784 .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
785 .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
786 .queueFamilyIndex = queue_family_index,
788 VkCommandBufferAllocateInfo cbuf_create = {
789 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
790 .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
791 .commandBufferCount = num_queues,
797 ret = vkCreateCommandPool(hwctx->
act_dev, &cqueue_create,
799 if (ret != VK_SUCCESS) {
809 cbuf_create.commandPool = cmd->
pool;
812 ret = vkAllocateCommandBuffers(hwctx->
act_dev, &cbuf_create, cmd->
bufs);
813 if (ret != VK_SUCCESS) {
824 for (
int i = 0;
i < num_queues;
i++) {
826 vkGetDeviceQueue(hwctx->
act_dev, queue_family_index,
i, &q->
queue);
843 vkWaitForFences(hwctx->
act_dev, 1, &q->
fence, VK_TRUE, UINT64_MAX);
888 VkCommandBufferBeginInfo cmd_start = {
889 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
890 .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
895 VkFenceCreateInfo fence_spawn = {
896 .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
898 ret = vkCreateFence(hwctx->
act_dev, &fence_spawn, hwctx->
alloc,
900 if (ret != VK_SUCCESS) {
906 vkWaitForFences(hwctx->
act_dev, 1, &q->
fence, VK_TRUE, UINT64_MAX);
914 if (ret != VK_SUCCESS) {
929 if (!deps || !nb_deps)
939 for (
int i = 0;
i < nb_deps;
i++) {
954 VkSubmitInfo *s_info,
int synchronous)
960 if (ret != VK_SUCCESS) {
968 s_info->commandBufferCount = 1;
970 ret = vkQueueSubmit(q->
queue, 1, s_info, q->
fence);
971 if (ret != VK_SUCCESS) {
980 vkWaitForFences(hwctx->
act_dev, 1, &q->
fence, VK_TRUE, UINT64_MAX);
999 pfn_vkDestroyDebugUtilsMessengerEXT(hwctx->
inst, p->
debug_ctx,
1003 vkDestroyInstance(hwctx->
inst, hwctx->
alloc);
1023 VkPhysicalDeviceFeatures dev_features = { 0 };
1024 VkDeviceQueueCreateInfo queue_create_info[3] = {
1025 { .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, },
1026 { .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, },
1027 { .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, },
1030 VkDeviceCreateInfo dev_info = {
1031 .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
1033 .pQueueCreateInfos = queue_create_info,
1034 .queueCreateInfoCount = 0,
1037 hwctx->
device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
1048 vkGetPhysicalDeviceFeatures(hwctx->
phys_dev, &dev_features);
1049 #define COPY_FEATURE(DST, NAME) (DST).features.NAME = dev_features.NAME; 1062 if ((err =
check_extensions(ctx, 1, opts, &dev_info.ppEnabledExtensionNames,
1063 &dev_info.enabledExtensionCount, 0))) {
1064 av_free((
void *)queue_create_info[0].pQueuePriorities);
1065 av_free((
void *)queue_create_info[1].pQueuePriorities);
1066 av_free((
void *)queue_create_info[2].pQueuePriorities);
1070 ret = vkCreateDevice(hwctx->
phys_dev, &dev_info, hwctx->
alloc,
1073 av_free((
void *)queue_create_info[0].pQueuePriorities);
1074 av_free((
void *)queue_create_info[1].pQueuePriorities);
1075 av_free((
void *)queue_create_info[2].pQueuePriorities);
1077 if (ret != VK_SUCCESS) {
1080 for (
int i = 0;
i < dev_info.enabledExtensionCount;
i++)
1081 av_free((
void *)dev_info.ppEnabledExtensionNames[
i]);
1082 av_free((
void *)dev_info.ppEnabledExtensionNames);
1109 optional_device_exts[j].
name)) {
1118 p->
props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
1120 p->
hprops.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT;
1124 p->
props.properties.deviceName);
1127 p->
props.properties.limits.optimalBufferCopyRowPitchAlignment);
1129 p->
props.properties.limits.minMemoryMapAlignment);
1132 p->
hprops.minImportedHostPointerAlignment);
1136 vkGetPhysicalDeviceQueueFamilyProperties(hwctx->
phys_dev, &queue_num,
NULL);
1142 #define CHECK_QUEUE(type, n) \ 1143 if (n >= queue_num) { \ 1144 av_log(ctx, AV_LOG_ERROR, "Invalid %s queue index %i (device has %i queues)!\n", \ 1145 type, n, queue_num); \ 1146 return AVERROR(EINVAL); \ 1164 vkGetPhysicalDeviceMemoryProperties(hwctx->
phys_dev, &p->
mprops);
1173 if (device && device[0]) {
1175 dev_select.
index = strtol(device, &end, 10);
1176 if (end == device) {
1177 dev_select.
index = 0;
1178 dev_select.
name = device;
1194 switch(src_ctx->
type) {
1200 const char *vendor = vaQueryVendorString(src_hwctx->
display);
1206 if (strstr(vendor,
"Intel"))
1207 dev_select.vendor_id = 0x8086;
1208 if (strstr(vendor,
"AMD"))
1209 dev_select.vendor_id = 0x1002;
1217 drmDevice *drm_dev_info;
1218 int err = drmGetDevice(src_hwctx->
fd, &drm_dev_info);
1224 if (drm_dev_info->bustype == DRM_BUS_PCI)
1225 dev_select.pci_device = drm_dev_info->deviceinfo.pci->device_id;
1227 drmFreeDevice(&drm_dev_info);
1237 CudaFunctions *cu = cu_internal->
cuda_dl;
1239 int ret =
CHECK_CU(cu->cuDeviceGetUuid((CUuuid *)&dev_select.uuid,
1246 dev_select.has_uuid = 1;
1257 const void *hwconfig,
1290 constraints->
max_width = p->
props.properties.limits.maxImageDimension2D;
1291 constraints->
max_height = p->
props.properties.limits.maxImageDimension2D;
1304 VkMemoryPropertyFlagBits req_flags,
const void *alloc_extension,
1305 VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem)
1311 VkMemoryAllocateInfo alloc_info = {
1312 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
1313 .pNext = alloc_extension,
1314 .allocationSize = req->size,
1319 for (
int i = 0;
i < p->
mprops.memoryTypeCount;
i++) {
1320 const VkMemoryType *
type = &p->
mprops.memoryTypes[
i];
1323 if (!(req->memoryTypeBits & (1 <<
i)))
1327 if ((type->propertyFlags & req_flags) != req_flags)
1331 if (req->size > p->
mprops.memoryHeaps[type->heapIndex].size)
1345 alloc_info.memoryTypeIndex =
index;
1347 ret = vkAllocateMemory(dev_hwctx->
act_dev, &alloc_info,
1348 dev_hwctx->
alloc, mem);
1349 if (ret != VK_SUCCESS) {
1355 *mem_flags |= p->
mprops.memoryTypes[
index].propertyFlags;
1366 if (internal->cuda_fc_ref) {
1372 CudaFunctions *cu = cu_internal->
cuda_dl;
1375 if (internal->cu_sem[
i])
1376 CHECK_CU(cu->cuDestroyExternalSemaphore(internal->cu_sem[
i]));
1377 if (internal->cu_mma[
i])
1378 CHECK_CU(cu->cuMipmappedArrayDestroy(internal->cu_mma[
i]));
1379 if (internal->ext_mem[
i])
1380 CHECK_CU(cu->cuDestroyExternalMemory(internal->ext_mem[
i]));
1409 void *alloc_pnext,
size_t alloc_pnext_stride)
1422 VkImageMemoryRequirementsInfo2 req_desc = {
1423 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
1426 VkMemoryDedicatedAllocateInfo ded_alloc = {
1427 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
1428 .pNext = (
void *)(((
uint8_t *)alloc_pnext) +
i*alloc_pnext_stride),
1430 VkMemoryDedicatedRequirements ded_req = {
1431 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
1433 VkMemoryRequirements2 req = {
1434 .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
1438 vkGetImageMemoryRequirements2(hwctx->
act_dev, &req_desc, &req);
1440 if (f->
tiling == VK_IMAGE_TILING_LINEAR)
1441 req.memoryRequirements.size =
FFALIGN(req.memoryRequirements.size,
1442 p->
props.properties.limits.minMemoryMapAlignment);
1445 use_ded_mem = ded_req.prefersDedicatedAllocation |
1446 ded_req.requiresDedicatedAllocation;
1448 ded_alloc.image = f->
img[
i];
1451 if ((err =
alloc_mem(ctx, &req.memoryRequirements,
1452 f->
tiling == VK_IMAGE_TILING_LINEAR ?
1453 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT :
1454 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
1455 use_ded_mem ? &ded_alloc : (
void *)ded_alloc.pNext,
1459 f->
size[
i] = req.memoryRequirements.size;
1460 bind_info[
i].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
1461 bind_info[
i].image = f->
img[
i];
1462 bind_info[
i].memory = f->
mem[
i];
1466 ret = vkBindImageMemory2(hwctx->
act_dev, planes, bind_info);
1467 if (ret != VK_SUCCESS) {
1487 VkImageLayout new_layout;
1488 VkAccessFlags new_access;
1493 VkSubmitInfo s_info = {
1494 .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
1495 .pSignalSemaphores = frame->
sem,
1496 .signalSemaphoreCount =
planes,
1501 wait_st[
i] = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1505 new_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
1506 new_access = VK_ACCESS_TRANSFER_WRITE_BIT;
1507 dst_qf = VK_QUEUE_FAMILY_IGNORED;
1510 new_layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
1511 new_access = VK_ACCESS_TRANSFER_READ_BIT;
1512 dst_qf = VK_QUEUE_FAMILY_IGNORED;
1515 new_layout = VK_IMAGE_LAYOUT_GENERAL;
1516 new_access = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
1517 dst_qf = VK_QUEUE_FAMILY_EXTERNAL_KHR;
1518 s_info.pWaitSemaphores = frame->
sem;
1519 s_info.pWaitDstStageMask = wait_st;
1520 s_info.waitSemaphoreCount =
planes;
1531 img_bar[
i].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
1532 img_bar[
i].srcAccessMask = 0x0;
1533 img_bar[
i].dstAccessMask = new_access;
1534 img_bar[
i].oldLayout = frame->
layout[
i];
1535 img_bar[
i].newLayout = new_layout;
1536 img_bar[
i].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1537 img_bar[
i].dstQueueFamilyIndex = dst_qf;
1538 img_bar[
i].image = frame->
img[
i];
1539 img_bar[
i].subresourceRange.levelCount = 1;
1540 img_bar[
i].subresourceRange.layerCount = 1;
1541 img_bar[
i].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1543 frame->
layout[
i] = img_bar[
i].newLayout;
1544 frame->
access[
i] = img_bar[
i].dstAccessMask;
1548 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1549 VK_PIPELINE_STAGE_TRANSFER_BIT,
1550 0, 0,
NULL, 0,
NULL, planes, img_bar);
1556 int frame_w,
int frame_h,
int plane)
1573 VkImageTiling tiling, VkImageUsageFlagBits
usage,
1585 VkExportSemaphoreCreateInfo ext_sem_info = {
1586 .sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
1587 .handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT,
1590 VkSemaphoreCreateInfo sem_spawn = {
1591 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
1603 VkImageCreateInfo create_info = {
1604 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
1605 .pNext = create_pnext,
1606 .imageType = VK_IMAGE_TYPE_2D,
1607 .format = img_fmts[
i],
1611 .flags = VK_IMAGE_CREATE_ALIAS_BIT,
1613 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
1615 .samples = VK_SAMPLE_COUNT_1_BIT,
1616 .pQueueFamilyIndices = p->
qfs,
1617 .queueFamilyIndexCount = p->
num_qfs,
1618 .sharingMode = p->
num_qfs > 1 ? VK_SHARING_MODE_CONCURRENT :
1619 VK_SHARING_MODE_EXCLUSIVE,
1622 get_plane_wh(&create_info.extent.width, &create_info.extent.height,
1625 ret = vkCreateImage(hwctx->
act_dev, &create_info,
1627 if (ret != VK_SUCCESS) {
1635 ret = vkCreateSemaphore(hwctx->
act_dev, &sem_spawn,
1637 if (ret != VK_SUCCESS) {
1643 f->
layout[
i] = create_info.initialLayout;
1660 VkExternalMemoryHandleTypeFlags *comp_handle_types,
1661 VkExternalMemoryHandleTypeFlagBits *iexp,
1662 VkExternalMemoryHandleTypeFlagBits
exp)
1667 VkExternalImageFormatProperties eprops = {
1668 .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR,
1670 VkImageFormatProperties2 props = {
1671 .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
1674 VkPhysicalDeviceExternalImageFormatInfo enext = {
1675 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
1678 VkPhysicalDeviceImageFormatInfo2 pinfo = {
1679 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
1680 .pNext = !exp ?
NULL : &enext,
1682 .type = VK_IMAGE_TYPE_2D,
1684 .usage = hwctx->
usage,
1685 .flags = VK_IMAGE_CREATE_ALIAS_BIT,
1688 ret = vkGetPhysicalDeviceImageFormatProperties2(dev_hwctx->
phys_dev,
1690 if (ret == VK_SUCCESS) {
1692 *comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes;
1706 VkExternalMemoryHandleTypeFlags e = 0x0;
1708 VkExternalMemoryImageCreateInfo eiinfo = {
1709 .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
1715 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT);
1719 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
1722 eminfo[
i].sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO;
1724 eminfo[
i].handleTypes = e;
1728 eiinfo.handleTypes ? &eiinfo :
NULL);
1772 VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
1857 !(map->
frame->
flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
1862 flush_ranges[
i].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
1864 flush_ranges[
i].size = VK_WHOLE_SIZE;
1867 ret = vkFlushMappedMemoryRanges(hwctx->
act_dev, planes,
1869 if (ret != VK_SUCCESS) {
1885 int err, mapped_mem_count = 0;
1901 if (!(f->
flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) ||
1902 !(f->
tiling == VK_IMAGE_TILING_LINEAR)) {
1913 ret = vkMapMemory(hwctx->act_dev, f->
mem[
i], 0,
1914 VK_WHOLE_SIZE, 0, (
void **)&dst->
data[
i]);
1915 if (ret != VK_SUCCESS) {
1926 !(f->
flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
1929 map_mem_ranges[
i].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
1930 map_mem_ranges[
i].size = VK_WHOLE_SIZE;
1931 map_mem_ranges[
i].memory = f->
mem[
i];
1934 ret = vkInvalidateMappedMemoryRanges(hwctx->act_dev, planes,
1936 if (ret != VK_SUCCESS) {
1945 VkImageSubresource
sub = {
1946 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
1948 VkSubresourceLayout
layout;
1949 vkGetImageSubresourceLayout(hwctx->act_dev, f->
img[
i], &sub, &layout);
1964 for (
int i = 0;
i < mapped_mem_count;
i++)
1965 vkUnmapMemory(hwctx->act_dev, f->
mem[
i]);
1987 static const struct {
1988 uint32_t drm_fourcc;
1990 } vulkan_drm_format_map[] = {
1991 { DRM_FORMAT_R8, VK_FORMAT_R8_UNORM },
1992 { DRM_FORMAT_R16, VK_FORMAT_R16_UNORM },
1993 { DRM_FORMAT_GR88, VK_FORMAT_R8G8_UNORM },
1994 { DRM_FORMAT_RG88, VK_FORMAT_R8G8_UNORM },
1995 { DRM_FORMAT_GR1616, VK_FORMAT_R16G16_UNORM },
1996 { DRM_FORMAT_RG1616, VK_FORMAT_R16G16_UNORM },
1997 { DRM_FORMAT_ARGB8888, VK_FORMAT_B8G8R8A8_UNORM },
1998 { DRM_FORMAT_XRGB8888, VK_FORMAT_B8G8R8A8_UNORM },
1999 { DRM_FORMAT_ABGR8888, VK_FORMAT_R8G8B8A8_UNORM },
2000 { DRM_FORMAT_XBGR8888, VK_FORMAT_R8G8B8A8_UNORM },
2003 static inline VkFormat drm_to_vulkan_fmt(uint32_t drm_fourcc)
2006 if (vulkan_drm_format_map[
i].drm_fourcc == drm_fourcc)
2007 return vulkan_drm_format_map[
i].vk_format;
2008 return VK_FORMAT_UNDEFINED;
2017 int bind_counts = 0;
2027 VkExternalMemoryHandleTypeFlagBits
htype = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
2032 if (drm_to_vulkan_fmt(desc->
layers[
i].
format) == VK_FORMAT_UNDEFINED) {
2045 f->
tiling = has_modifiers ? VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT :
2047 VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
2051 VkImageDrmFormatModifierExplicitCreateInfoEXT drm_info = {
2052 .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT,
2054 .drmFormatModifierPlaneCount =
planes,
2055 .pPlaneLayouts = (
const VkSubresourceLayout *)&plane_data,
2058 VkExternalMemoryImageCreateInfo einfo = {
2059 .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
2060 .pNext = has_modifiers ? &drm_info :
NULL,
2061 .handleTypes =
htype,
2064 VkSemaphoreCreateInfo sem_spawn = {
2065 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
2068 VkImageCreateInfo create_info = {
2069 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
2071 .imageType = VK_IMAGE_TYPE_2D,
2076 .flags = VK_IMAGE_CREATE_ALIAS_BIT,
2078 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
2079 .usage = frames_hwctx->
usage,
2080 .samples = VK_SAMPLE_COUNT_1_BIT,
2081 .pQueueFamilyIndices = p->
qfs,
2082 .queueFamilyIndexCount = p->
num_qfs,
2083 .sharingMode = p->
num_qfs > 1 ? VK_SHARING_MODE_CONCURRENT :
2084 VK_SHARING_MODE_EXCLUSIVE,
2087 get_plane_wh(&create_info.extent.width, &create_info.extent.height,
2090 for (
int j = 0; j <
planes; j++) {
2093 plane_data[j].size = 0;
2094 plane_data[j].arrayPitch = 0;
2095 plane_data[j].depthPitch = 0;
2099 ret = vkCreateImage(hwctx->
act_dev, &create_info,
2101 if (ret != VK_SUCCESS) {
2108 ret = vkCreateSemaphore(hwctx->
act_dev, &sem_spawn,
2110 if (ret != VK_SUCCESS) {
2121 f->
layout[
i] = create_info.initialLayout;
2126 int use_ded_mem = 0;
2127 VkMemoryFdPropertiesKHR fdmp = {
2128 .sType = VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR,
2130 VkMemoryRequirements req = {
2133 VkImportMemoryFdInfoKHR idesc = {
2134 .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
2135 .handleType =
htype,
2138 VkMemoryDedicatedAllocateInfo ded_alloc = {
2139 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
2143 ret = pfn_vkGetMemoryFdPropertiesKHR(hwctx->
act_dev, htype,
2145 if (ret != VK_SUCCESS) {
2153 req.memoryTypeBits = fdmp.memoryTypeBits;
2159 VkImageMemoryRequirementsInfo2 req_desc = {
2160 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
2163 VkMemoryDedicatedRequirements ded_req = {
2164 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
2166 VkMemoryRequirements2 req2 = {
2167 .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
2171 vkGetImageMemoryRequirements2(hwctx->
act_dev, &req_desc, &req2);
2173 use_ded_mem = ded_req.prefersDedicatedAllocation |
2174 ded_req.requiresDedicatedAllocation;
2176 ded_alloc.image = f->
img[
i];
2179 err =
alloc_mem(ctx, &req, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
2180 use_ded_mem ? &ded_alloc : ded_alloc.pNext,
2192 const int signal_p = has_modifiers && (planes > 1);
2193 for (
int j = 0; j <
planes; j++) {
2194 VkImageAspectFlagBits aspect = j == 0 ? VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT :
2195 j == 1 ? VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT :
2196 VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT;
2198 plane_info[bind_counts].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO;
2199 plane_info[bind_counts].planeAspect = aspect;
2201 bind_info[bind_counts].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
2202 bind_info[bind_counts].pNext = signal_p ? &plane_info[bind_counts] :
NULL;
2203 bind_info[bind_counts].image = f->
img[
i];
2211 ret = vkBindImageMemory2(hwctx->
act_dev, bind_counts, bind_info);
2212 if (ret != VK_SUCCESS) {
2249 err = vulkan_map_from_drm_frame_desc(hwfc, &f,
2267 &vulkan_unmap_from, map);
2290 VASurfaceID surface_id = (VASurfaceID)(uintptr_t)src->
data[3];
2296 vaSyncSurface(vaapi_ctx->display, surface_id);
2304 err = vulkan_map_from_drm(dst_fc, dst, tmp, flags);
2337 CudaFunctions *cu = cu_internal->
cuda_dl;
2338 CUarray_format cufmt = desc->
comp[0].
depth > 8 ? CU_AD_FORMAT_UNSIGNED_INT16 :
2339 CU_AD_FORMAT_UNSIGNED_INT8;
2344 if (!dst_int || !dst_int->cuda_fc_ref) {
2354 if (!dst_int->cuda_fc_ref) {
2360 CUDA_EXTERNAL_MEMORY_MIPMAPPED_ARRAY_DESC tex_desc = {
2365 .NumChannels = 1 + ((planes == 2) &&
i),
2370 CUDA_EXTERNAL_MEMORY_HANDLE_DESC ext_desc = {
2371 .type = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD,
2372 .size = dst_f->
size[
i],
2374 VkMemoryGetFdInfoKHR export_info = {
2375 .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
2376 .memory = dst_f->
mem[
i],
2377 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
2379 VkSemaphoreGetFdInfoKHR sem_export = {
2380 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
2381 .semaphore = dst_f->
sem[
i],
2382 .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT,
2384 CUDA_EXTERNAL_SEMAPHORE_HANDLE_DESC ext_sem_desc = {
2385 .type = CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD,
2391 tex_desc.arrayDesc.Width = p_w;
2392 tex_desc.arrayDesc.Height = p_h;
2394 ret = pfn_vkGetMemoryFdKHR(hwctx->
act_dev, &export_info,
2395 &ext_desc.handle.fd);
2396 if (ret != VK_SUCCESS) {
2402 ret =
CHECK_CU(cu->cuImportExternalMemory(&dst_int->ext_mem[
i], &ext_desc));
2408 ret =
CHECK_CU(cu->cuExternalMemoryGetMappedMipmappedArray(&dst_int->cu_mma[
i],
2409 dst_int->ext_mem[
i],
2416 ret =
CHECK_CU(cu->cuMipmappedArrayGetLevel(&dst_int->cu_array[
i],
2417 dst_int->cu_mma[
i], 0));
2423 ret = pfn_vkGetSemaphoreFdKHR(hwctx->
act_dev, &sem_export,
2424 &ext_sem_desc.handle.fd);
2425 if (ret != VK_SUCCESS) {
2432 ret =
CHECK_CU(cu->cuImportExternalSemaphore(&dst_int->cu_sem[
i],
2462 CudaFunctions *cu = cu_internal->
cuda_dl;
2466 ret =
CHECK_CU(cu->cuCtxPushCurrent(cuda_dev->cuda_ctx));
2478 dst_int = dst_f->internal;
2480 ret =
CHECK_CU(cu->cuWaitExternalSemaphoresAsync(dst_int->cu_sem, s_w_par,
2481 planes, cuda_dev->stream));
2488 CUDA_MEMCPY2D cpy = {
2489 .srcMemoryType = CU_MEMORYTYPE_DEVICE,
2490 .srcDevice = (CUdeviceptr)src->
data[
i],
2494 .dstMemoryType = CU_MEMORYTYPE_ARRAY,
2495 .dstArray = dst_int->cu_array[
i],
2501 cpy.WidthInBytes = p_w * desc->comp[
i].step;
2504 ret =
CHECK_CU(cu->cuMemcpy2DAsync(&cpy, cuda_dev->stream));
2511 ret =
CHECK_CU(cu->cuSignalExternalSemaphoresAsync(dst_int->cu_sem, s_s_par,
2512 planes, cuda_dev->stream));
2527 dst_f->internal =
NULL;
2543 return vulkan_map_from_vaapi(hwfc, dst, src, flags);
2547 return vulkan_map_from_drm(hwfc, dst, src, flags);
2555 typedef struct VulkanDRMMapping {
2570 static inline uint32_t vulkan_fmt_to_drm(VkFormat vkfmt)
2573 if (vulkan_drm_format_map[
i].vk_format == vkfmt)
2574 return vulkan_drm_format_map[
i].drm_fourcc;
2575 return DRM_FORMAT_INVALID;
2589 VkImageDrmFormatModifierPropertiesEXT drm_mod = {
2590 .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT,
2606 VK_LOAD_PFN(hwctx->inst, vkGetImageDrmFormatModifierPropertiesEXT);
2607 ret = pfn_vkGetImageDrmFormatModifierPropertiesEXT(hwctx->act_dev, f->
img[0],
2609 if (ret != VK_SUCCESS) {
2617 VkMemoryGetFdInfoKHR export_info = {
2618 .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
2619 .memory = f->
mem[
i],
2620 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
2623 ret = pfn_vkGetMemoryFdKHR(hwctx->act_dev, &export_info,
2625 if (ret != VK_SUCCESS) {
2638 VkSubresourceLayout
layout;
2639 VkImageSubresource
sub = {
2641 VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT :
2642 VK_IMAGE_ASPECT_COLOR_BIT,
2646 drm_desc->
layers[
i].
format = vulkan_fmt_to_drm(plane_vkfmt);
2657 if (f->
tiling == VK_IMAGE_TILING_OPTIMAL)
2660 vkGetImageSubresourceLayout(hwctx->act_dev, f->
img[
i], &sub, &layout);
2689 err = vulkan_map_to_drm(hwfc, tmp, src, flags);
2715 return vulkan_map_to_drm(hwfc, dst, src, flags);
2719 return vulkan_map_to_vaapi(hwfc, dst, src, flags);
2751 *stride =
FFALIGN(*stride, p->
props.properties.limits.optimalBufferCopyRowPitchAlignment);
2752 size = height*(*stride);
2753 size =
FFALIGN(size, p->
props.properties.limits.minMemoryMapAlignment);
2758 VkBufferUsageFlags
usage, VkMemoryPropertyFlagBits
flags,
2759 size_t size, uint32_t req_memory_bits,
int host_mapped,
2760 void *create_pnext,
void *alloc_pnext)
2767 VkBufferCreateInfo buf_spawn = {
2768 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
2769 .pNext = create_pnext,
2772 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
2775 VkBufferMemoryRequirementsInfo2 req_desc = {
2776 .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
2778 VkMemoryDedicatedAllocateInfo ded_alloc = {
2779 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
2780 .pNext = alloc_pnext,
2782 VkMemoryDedicatedRequirements ded_req = {
2783 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
2785 VkMemoryRequirements2 req = {
2786 .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
2796 ret = vkCreateBuffer(hwctx->
act_dev, &buf_spawn,
NULL, &vkbuf->
buf);
2797 if (ret != VK_SUCCESS) {
2804 req_desc.buffer = vkbuf->
buf;
2806 vkGetBufferMemoryRequirements2(hwctx->
act_dev, &req_desc, &req);
2809 use_ded_mem = ded_req.prefersDedicatedAllocation |
2810 ded_req.requiresDedicatedAllocation;
2812 ded_alloc.buffer = vkbuf->
buf;
2815 if (req_memory_bits)
2816 req.memoryRequirements.memoryTypeBits &= req_memory_bits;
2818 err =
alloc_mem(ctx, &req.memoryRequirements, flags,
2819 use_ded_mem ? &ded_alloc : (
void *)ded_alloc.pNext,
2824 ret = vkBindBufferMemory(hwctx->
act_dev, vkbuf->
buf, vkbuf->
mem, 0);
2825 if (ret != VK_SUCCESS) {
2847 int nb_buffers,
int invalidate)
2852 int invalidate_count = 0;
2854 for (
int i = 0;
i < nb_buffers;
i++) {
2859 ret = vkMapMemory(hwctx->
act_dev, vkbuf->
mem, 0,
2860 VK_WHOLE_SIZE, 0, (
void **)&mem[
i]);
2861 if (ret != VK_SUCCESS) {
2871 for (
int i = 0;
i < nb_buffers;
i++) {
2873 const VkMappedMemoryRange ival_buf = {
2874 .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
2875 .memory = vkbuf->
mem,
2876 .size = VK_WHOLE_SIZE,
2885 if (vkbuf->
flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
2888 invalidate_ctx[invalidate_count++] = ival_buf;
2891 if (invalidate_count) {
2892 ret = vkInvalidateMappedMemoryRanges(hwctx->
act_dev, invalidate_count,
2894 if (ret != VK_SUCCESS)
2903 int nb_buffers,
int flush)
2909 int flush_count = 0;
2912 for (
int i = 0;
i < nb_buffers;
i++) {
2914 const VkMappedMemoryRange flush_buf = {
2915 .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
2916 .memory = vkbuf->
mem,
2917 .size = VK_WHOLE_SIZE,
2920 if (vkbuf->
flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
2923 flush_ctx[flush_count++] = flush_buf;
2928 ret = vkFlushMappedMemoryRanges(hwctx->
act_dev, flush_count, flush_ctx);
2929 if (ret != VK_SUCCESS) {
2936 for (
int i = 0;
i < nb_buffers;
i++) {
2949 const int *buf_stride,
int w,
2966 VkSubmitInfo s_info = {
2967 .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
2968 .pSignalSemaphores = frame->
sem,
2969 .pWaitSemaphores = frame->
sem,
2970 .pWaitDstStageMask = sem_wait_dst,
2971 .signalSemaphoreCount =
planes,
2972 .waitSemaphoreCount =
planes,
2980 VkImageLayout new_layout = to_buf ? VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL :
2981 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
2982 VkAccessFlags new_access = to_buf ? VK_ACCESS_TRANSFER_READ_BIT :
2983 VK_ACCESS_TRANSFER_WRITE_BIT;
2985 sem_wait_dst[
i] = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
2988 if ((frame->
layout[
i] == new_layout) && (frame->
access[
i] & new_access))
2991 img_bar[bar_num].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
2992 img_bar[bar_num].srcAccessMask = 0x0;
2993 img_bar[bar_num].dstAccessMask = new_access;
2994 img_bar[bar_num].oldLayout = frame->
layout[
i];
2995 img_bar[bar_num].newLayout = new_layout;
2996 img_bar[bar_num].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
2997 img_bar[bar_num].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
2998 img_bar[bar_num].image = frame->
img[
i];
2999 img_bar[bar_num].subresourceRange.levelCount = 1;
3000 img_bar[bar_num].subresourceRange.layerCount = 1;
3001 img_bar[bar_num].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3003 frame->
layout[
i] = img_bar[bar_num].newLayout;
3004 frame->
access[
i] = img_bar[bar_num].dstAccessMask;
3010 vkCmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
3011 VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
3012 0,
NULL, 0,
NULL, bar_num, img_bar);
3017 VkBufferImageCopy buf_reg = {
3018 .bufferOffset = buf_offsets[
i],
3019 .bufferRowLength = buf_stride[
i] / desc->
comp[
i].
step,
3020 .imageSubresource.layerCount = 1,
3021 .imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
3022 .imageOffset = { 0, 0, 0, },
3028 buf_reg.bufferImageHeight = p_h;
3029 buf_reg.imageExtent = (VkExtent3D){ p_w, p_h, 1, };
3032 vkCmdCopyImageToBuffer(cmd_buf, frame->
img[
i], frame->
layout[
i],
3033 vkbuf->
buf, 1, &buf_reg);
3035 vkCmdCopyBufferToImage(cmd_buf, vkbuf->
buf, frame->
img[
i],
3036 frame->
layout[
i], 1, &buf_reg);
3081 VK_LOAD_PFN(hwctx->inst, vkGetMemoryHostPointerPropertiesEXT);
3088 if (swf->width > hwfc->
width || swf->height > hwfc->
height)
3092 if (
f->tiling == VK_IMAGE_TILING_LINEAR &&
3093 f->flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
3097 map->
format = swf->format;
3112 VkExternalMemoryBufferCreateInfo create_desc = {
3113 .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
3114 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,
3117 VkImportMemoryHostPointerInfoEXT import_desc = {
3118 .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT,
3119 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,
3122 VkMemoryHostPointerPropertiesEXT p_props = {
3123 .sType = VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT,
3126 get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height,
i);
3131 if (map_host && swf->linesize[
i] > 0) {
3133 offs = (uintptr_t)swf->data[
i] % p->hprops.minImportedHostPointerAlignment;
3134 import_desc.pHostPointer = swf->data[
i] - offs;
3139 p->hprops.minImportedHostPointerAlignment);
3141 ret = pfn_vkGetMemoryHostPointerPropertiesEXT(hwctx->act_dev,
3142 import_desc.handleType,
3143 import_desc.pHostPointer,
3146 if (
ret == VK_SUCCESS) {
3148 buf_offsets[
i] = offs;
3152 if (!host_mapped[
i])
3156 from ? VK_BUFFER_USAGE_TRANSFER_DST_BIT :
3157 VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
3158 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
3159 req_size, p_props.memoryTypeBits, host_mapped[i],
3160 host_mapped[i] ? &create_desc :
NULL,
3161 host_mapped[i] ? &import_desc : NULL);
3171 for (
int i = 0; i <
planes; i++) {
3175 get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i);
3178 (
const uint8_t *)swf->data[i], swf->linesize[i],
3189 swf->width, swf->height, swf->format,
from);
3196 for (
int i = 0; i <
planes; i++) {
3200 get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i);
3213 for (
int i = 0; i <
planes; i++)
3229 return vulkan_transfer_data_from_cuda(hwfc, dst, src);
3255 CudaFunctions *cu = cu_internal->
cuda_dl;
3259 ret =
CHECK_CU(cu->cuCtxPushCurrent(cuda_dev->cuda_ctx));
3271 dst_int = dst_f->internal;
3273 ret =
CHECK_CU(cu->cuWaitExternalSemaphoresAsync(dst_int->cu_sem, s_w_par,
3274 planes, cuda_dev->stream));
3280 for (
int i = 0; i <
planes; i++) {
3281 CUDA_MEMCPY2D cpy = {
3282 .dstMemoryType = CU_MEMORYTYPE_DEVICE,
3283 .dstDevice = (CUdeviceptr)dst->
data[i],
3287 .srcMemoryType = CU_MEMORYTYPE_ARRAY,
3288 .srcArray = dst_int->cu_array[i],
3294 cpy.WidthInBytes = w * desc->comp[
i].step;
3297 ret =
CHECK_CU(cu->cuMemcpy2DAsync(&cpy, cuda_dev->stream));
3304 ret =
CHECK_CU(cu->cuSignalExternalSemaphoresAsync(dst_int->cu_sem, s_s_par,
3305 planes, cuda_dev->stream));
3320 dst_f->internal =
NULL;
3336 return vulkan_transfer_data_to_cuda(hwfc, dst, src);
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
static void vulkan_frame_free(void *opaque, uint8_t *data)
ptrdiff_t const GLvoid GLenum usage
#define AV_PIX_FMT_YUVA422P16
static enum AVPixelFormat pix_fmt
static void unref_exec_ctx_deps(AVHWFramesContext *hwfc, VulkanExecCtx *cmd)
#define AV_NUM_DATA_POINTERS
static const char * vk_dev_type(enum VkPhysicalDeviceType type)
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it...
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
This structure describes decoded (raw) audio or video data.
static int map_buffers(AVHWDeviceContext *ctx, AVBufferRef **bufs, uint8_t *mem[], int nb_buffers, int invalidate)
static VkBool32 vk_dbg_callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT *data, void *priv)
struct AVVkFrameInternal * internal
Internal data.
ptrdiff_t const GLvoid * data
static void flush(AVCodecContext *avctx)
#define AV_PIX_FMT_YUVA420P10
#define LIBAVUTIL_VERSION_MAJOR
static int create_buf(AVHWDeviceContext *ctx, AVBufferRef **buf, VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags, size_t size, uint32_t req_memory_bits, int host_mapped, void *create_pnext, void *alloc_pnext)
#define VK_LOAD_PFN(inst, name)
#define AV_PIX_FMT_YUVA422P10
The mapping must be readable.
static int linear(InterplayACMContext *s, unsigned ind, unsigned col)
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
#define AV_LOG_WARNING
Something somehow does not look correct.
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
packed RGB 8:8:8, 24bpp, RGBRGB...
static int check_extensions(AVHWDeviceContext *ctx, int dev, AVDictionary *opts, const char *const **dst, uint32_t *num, int debug)
VkDeviceMemory mem[AV_NUM_DATA_POINTERS]
Memory backing the images.
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
#define AV_PIX_FMT_RGBA64
AVCUDADeviceContextInternal * internal
int width
The allocated dimensions of the frames in this pool.
VkDevice act_dev
Active device.
int nb_enabled_inst_extensions
#define AV_PIX_FMT_YUV420P12
static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
static const char * vk_ret2str(VkResult res)
int queue_family_tx_index
Queue family index to use for transfer operations, and the amount of queues enabled.
VulkanExecCtx download_ctx
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
static void free_buf(void *opaque, uint8_t *data)
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample format(the sample packing is implied by the sample format) and sample rate.The lists are not just lists
const HWContextType ff_hwcontext_type_vulkan
const VkFormat * av_vkfmt_from_pixfmt(enum AVPixelFormat p)
Returns the format of each image up to the number of planes for a given sw_format.
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
int max_width
The maximum size of frames in this hw_frames_ctx.
int nb_objects
Number of DRM objects making up this frame.
const char *const * enabled_dev_extensions
Enabled device extensions.
VkMemoryPropertyFlagBits flags
OR'd flags for all memory allocated.
VkImage img[AV_NUM_DATA_POINTERS]
Vulkan images to which the memory is bound to.
API-specific header for AV_HWDEVICE_TYPE_VAAPI.
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame...
void * create_pnext
Extension data for image creation.
VkPhysicalDeviceFeatures2 device_features
This structure should be set to the set of features that present and enabled during device creation...
static int vulkan_map_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
static int search_queue_families(AVHWDeviceContext *ctx, VkDeviceCreateInfo *cd)
static int vulkan_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame)
VkPhysicalDeviceProperties2 props
#define CHECK_QUEUE(type, n)
AVBufferPool * pool_internal
static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame, VkImageTiling tiling, VkImageUsageFlagBits usage, void *create_pnext)
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
int queue_family_index
Queue family index for graphics.
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
static const struct @312 vk_pixfmt_map[]
static av_cold int end(AVCodecContext *avctx)
size_t size
Total size of the object.
VkPhysicalDeviceExternalMemoryHostPropertiesEXT hprops
static int transfer_image_buf(AVHWFramesContext *hwfc, const AVFrame *f, AVBufferRef **bufs, size_t *buf_offsets, const int *buf_stride, int w, int h, enum AVPixelFormat pix_fmt, int to_buf)
int queue_family_comp_index
Queue family index for compute ops, and the amount of queues enabled.
static int find_device(AVHWDeviceContext *ctx, VulkanDeviceSelection *select)
static cqueue * cqueue_create(int size, int max_size)
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
AVDRMLayerDescriptor layers[AV_DRM_MAX_PLANES]
Array of layers in the frame.
#define AV_LOG_VERBOSE
Detailed information.
#define AV_PIX_FMT_YUV444P16
const char *const * enabled_inst_extensions
Enabled instance extensions.
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a source
#define AV_PIX_FMT_YUV422P12
static int alloc_mem(AVHWDeviceContext *ctx, VkMemoryRequirements *req, VkMemoryPropertyFlagBits req_flags, const void *alloc_extension, VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem)
#define AV_PIX_FMT_YUVA420P16
static int vulkan_transfer_data_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src)
static int vulkan_frames_get_constraints(AVHWDeviceContext *ctx, const void *hwconfig, AVHWFramesConstraints *constraints)
int fd
DRM PRIME fd for the object.
Allocated as AVHWFramesContext.hwctx, used to set pool-specific options.
int nb_layers
Number of layers in the frame.
planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
int object_index
Index of the object containing this plane in the objects array of the enclosing frame descriptor...
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
#define AV_PIX_FMT_FLAG_RGB
The pixel format contains RGB-like data (as opposed to YUV/grayscale).
static void try_export_flags(AVHWFramesContext *hwfc, VkExternalMemoryHandleTypeFlags *comp_handle_types, VkExternalMemoryHandleTypeFlagBits *iexp, VkExternalMemoryHandleTypeFlagBits exp)
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
ptrdiff_t pitch
Pitch (linesize) of this plane.
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
#define LIBAVUTIL_VERSION_MICRO
#define AV_PIX_FMT_YUVA444P16
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
static int wait_start_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd)
VkDebugUtilsMessengerEXT debug_ctx
#define AV_PIX_FMT_0BGR32
API-specific header for AV_HWDEVICE_TYPE_VULKAN.
#define AV_PIX_FMT_YUV444P10
int nb_planes
Number of planes in the layer.
AVBufferRef * av_buffer_create(uint8_t *data, int size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
enum AVHWDeviceType type
This field identifies the underlying API used for hardware access.
#define AV_PIX_FMT_GBRAP16
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
int av_frame_copy(AVFrame *dst, const AVFrame *src)
Copy the frame data from src to dst.
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
static void free_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd)
uint64_t flags
Combination of AV_PIX_FMT_FLAG_...
planar YUV 4:4:4, 24bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
as above, but U and V bytes are swapped
void * alloc_pnext[AV_NUM_DATA_POINTERS]
Extension data for memory allocation.
VkInstance inst
Vulkan instance.
#define AV_PIX_FMT_GRAY16
AVDRMPlaneDescriptor planes[AV_DRM_MAX_PLANES]
Array of planes in this layer.
AVHWDeviceContext * device_ctx
The parent AVHWDeviceContext.
#define AV_PIX_FMT_YUVA444P12
static const VulkanOptExtension optional_instance_exts[]
VkAccessFlagBits access[AV_NUM_DATA_POINTERS]
Updated after every barrier.
static size_t get_req_buffer_size(VulkanDevicePriv *p, int *stride, int height)
VkMemoryPropertyFlagBits flags
static int vulkan_device_create(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags)
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
#define AV_PIX_FMT_X2RGB10
Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
void * av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
Reallocate the given buffer if it is not large enough, otherwise do nothing.
FFmpeg internal API for CUDA.
static void vulkan_free_internal(AVVkFrameInternal *internal)
VkImageUsageFlagBits usage
Defines extra usage of output frames.
packed RGB 8:8:8, 24bpp, BGRBGR...
#define AV_PIX_FMT_YUVA444P10
AVDRMObjectDescriptor objects[AV_DRM_MAX_PLANES]
Array of objects making up the frame.
static AVBufferRef * vulkan_pool_alloc(void *opaque, int size)
uint64_t format_modifier
Format modifier applied to the object (DRM_FORMAT_MOD_*).
HW acceleration through CUDA.
AVBufferPool * av_buffer_pool_init2(int size, void *opaque, AVBufferRef *(*alloc)(void *opaque, int size), void(*pool_free)(void *opaque))
Allocate and initialize a buffer pool with a more complex allocator.
#define FF_ARRAY_ELEMS(a)
static VkCommandBuffer get_buf_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd)
static int unmap_buffers(AVHWDeviceContext *ctx, AVBufferRef **bufs, int nb_buffers, int flush)
VADisplay display
The VADisplay handle, to be filled by the user.
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
#define AV_PIX_FMT_YUV420P16
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
The mapped frame will be overwritten completely in subsequent operations, so the current frame data n...
int min_width
The minimum size of frames in this hw_frames_ctx.
#define AV_LOG_INFO
Standard information.
enum AVPixelFormat pixfmt
char * av_strdup(const char *s)
Duplicate a string.
void * priv
Hardware-specific private data associated with the mapping.
#define AV_PIX_FMT_GRAYF32
static void vulkan_frames_uninit(AVHWFramesContext *hwfc)
This struct describes the constraints on hardware frames attached to a given device with a hardware-s...
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, AVVkFrame *frame, enum PrepMode pmode)
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
static int vulkan_device_create_internal(AVHWDeviceContext *ctx, VulkanDeviceSelection *dev_select, AVDictionary *opts, int flags)
static int mod(int a, int b)
Modulo operation with only positive remainders.
uint8_t * data
The data buffer.
int ff_hwframe_map_replace(AVFrame *dst, const AVFrame *src)
Replace the current hwmap of dst with the one from src, used for indirect mappings like VAAPI->(DRM)-...
static const struct @324 planes[]
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
static int vulkan_device_derive(AVHWDeviceContext *ctx, AVHWDeviceContext *src_ctx, AVDictionary *opts, int flags)
The mapping must be writeable.
#define AV_PIX_FMT_YUV420P10
This struct is allocated as AVHWDeviceContext.hwctx.
int ff_hwframe_map_create(AVBufferRef *hwframe_ref, AVFrame *dst, const AVFrame *src, void(*unmap)(AVHWFramesContext *ctx, HWMapDescriptor *hwmap), void *priv)
as above, but U and V bytes are swapped
DRM-managed buffers exposed through PRIME buffer sharing.
This struct describes a set or pool of "hardware" frames (i.e.
#define GET_QUEUE_COUNT(hwctx, graph, comp, tx)
#define SEARCH_FLAGS(expr, out)
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
enum AVPixelFormat * valid_hw_formats
A list of possible values for format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
const VDPAUPixFmtMap * map
API-specific header for AV_HWDEVICE_TYPE_DRM.
AVHWFramesInternal * internal
Private data used internally by libavutil.
#define AV_PIX_FMT_BGR565
#define flags(name, subs,...)
#define AV_PIX_FMT_YUV422P10
#define AV_PIX_FMT_YUV444P12
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
static int add_buf_dep_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, AVBufferRef *const *deps, int nb_deps)
VkImageTiling tiling
The same tiling must be used for all images in the frame.
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok()...
static int vulkan_transfer_data(AVHWFramesContext *hwfc, const AVFrame *vkf, const AVFrame *swf, int from)
#define AV_PIX_FMT_GBRPF32
A reference to a data buffer.
GLint GLenum GLboolean GLsizei stride
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
static const VulkanOptExtension optional_device_exts[]
#define DEFAULT_USAGE_FLAGS
#define AV_PIX_FMT_GBRAPF32
int nb_enabled_dev_extensions
static int ref[MAX_W *MAX_W]
int fd
File descriptor of DRM device.
size_t size[AV_NUM_DATA_POINTERS]
planar GBRA 4:4:4:4 32bpp
static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, void *alloc_pnext, size_t alloc_pnext_stride)
#define LIBAVUTIL_VERSION_MINOR
VkSemaphore sem[AV_NUM_DATA_POINTERS]
Synchronization semaphores.
int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags)
Map a hardware frame.
#define ADD_VAL_TO_LIST(list, count, val)
AVBufferRef * av_buffer_ref(AVBufferRef *buf)
Create a new reference to an AVBuffer.
static int vulkan_frames_init(AVHWFramesContext *hwfc)
static void vulkan_device_free(AVHWDeviceContext *ctx)
uint32_t format
Format of the layer (DRM_FORMAT_*).
VkPhysicalDeviceMemoryProperties mprops
uint8_t uuid[VK_UUID_SIZE]
interleaved chroma YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
static int vulkan_frames_derive_to(AVHWFramesContext *dst_fc, AVHWFramesContext *src_fc, int flags)
static int vulkan_map_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
static int vulkan_transfer_get_formats(AVHWFramesContext *hwfc, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats)
AVHWFrameTransferDirection
static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts)
AVBufferPool * pool
A pool from which the frames are allocated by av_hwframe_get_buffer().
enum AVPixelFormat * valid_sw_formats
A list of possible values for sw_format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
AVVkFrame * av_vk_frame_alloc(void)
Allocates a single AVVkFrame and initializes everything as 0.
static int pixfmt_is_supported(AVVulkanDeviceContext *hwctx, enum AVPixelFormat p, int linear)
static int vulkan_device_init(AVHWDeviceContext *ctx)
ptrdiff_t offset
Offset within that object of this plane.
static int submit_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, VkSubmitInfo *s_info, int synchronous)
static void vulkan_unmap_frame(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap)
VAAPI connection details.
static void get_plane_wh(int *w, int *h, enum AVPixelFormat format, int frame_w, int frame_h, int plane)
VkPhysicalDevice phys_dev
Physical device.
#define AV_PIX_FMT_RGB565
VkImageLayout layout[AV_NUM_DATA_POINTERS]
number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of...
VkImageTiling tiling
Controls the tiling of allocated frames.
void(* free)(struct AVHWDeviceContext *ctx)
This field may be set by the caller before calling av_hwdevice_ctx_init().
static float sub(float src0, float src1)
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
#define av_malloc_array(a, b)
void av_image_copy_plane(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int bytewidth, int height)
Copy image plane from src to dst.
AVHWDeviceInternal * internal
Private data used internally by libavutil.
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
static int vulkan_transfer_data_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src)
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
int depth
Number of bits in the component.
static int create_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, int queue_family_index, int num_queues)
#define ADD_QUEUE(fidx, graph, comp, tx)
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
#define AVERROR_EXTERNAL
Generic error in an external library.
AVPixelFormat
Pixel format.
#define AV_PIX_FMT_FLAG_PLANAR
At least one pixel component is not in the first data plane.
#define COPY_FEATURE(DST, NAME)
#define AV_PIX_FMT_YUV422P16
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel layout
const VkAllocationCallbacks * alloc
Custom memory allocator, else NULL.
int step
Number of elements between 2 horizontally consecutive pixels.
#define AV_PIX_FMT_YUVA422P12
#define AV_CEIL_RSHIFT(a, b)
void * av_mallocz_array(size_t nmemb, size_t size)