From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.ffmpeg.org (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTPS id CBC464A9E6 for ; Thu, 19 Jun 2025 23:16:52 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTP id BB84968D908; Fri, 20 Jun 2025 02:16:48 +0300 (EEST) Received: from mail-pj1-f42.google.com (mail-pj1-f42.google.com [209.85.216.42]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTPS id 4E4A068CF15 for ; Fri, 20 Jun 2025 02:16:42 +0300 (EEST) Received: by mail-pj1-f42.google.com with SMTP id 98e67ed59e1d1-3141f9ce4d1so1041293a91.2 for ; Thu, 19 Jun 2025 16:16:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1750375000; x=1750979800; darn=ffmpeg.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=hFQ7isrmVQ4+NrCrRsxjKfTeDyLWpzjvx/U0FBZFUYA=; b=gv9GsnF+ojf/UCf5rj5Xxez3hGGsC2YLiTcFrA+/K2c1BqvtD999KH4/aPScg+DxmS 5xNPhm6uRUKdP56uFr3sLJPV6BdQgajZF+ZQywun93UVNdpMaG7WVeCprCmbcKQEMlXT bXdCPX9AEYtychybJhewxTDX3Mpc/C10yDTK36TN1flBpeA/SJr76sR1RsCq0ovHRY86 9YEElv6r83qfaWVkwfTJn7Zhorir2hnOqMU+XqCsS12xNDJ3uxK5Doaewa2Au3UUgka2 p9IKlofgFzD3czB0hrGgv5pP1PJG0v3y4aptNP30iiLgCTLp45zhbLQ3Etbkn5maqKyM s2jw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750375000; x=1750979800; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=hFQ7isrmVQ4+NrCrRsxjKfTeDyLWpzjvx/U0FBZFUYA=; b=Id+O4YgGAGugIpBkM1SDzMndGqyftSWdS9YKzim4CtLpFSYXJmtmJ5xxE2zH0z9SFN yGRIn04+VhYI24lovoCdJItsV8Rs/T8nC6shLB48PN0rWHjyFS/+1vpjl+oyBQ87HwL/ aglhntO+xliYmkjrWyfnhEmFeogFDit21jBsbyrUlbSMCZXarhAqFdE9eLhNAMi1K3+s BJtf2qcqiIaqCmeDqywGT23S66bIrBI65LRab1i8LagfzvCcKVHZDo3B/Fo5PBxQSlXl FDhyuWLeYDoo3X/JO7Tt1Hc3tNm/cJSXIc/dGuOQp/8JoNae12w/gZ4jSv+vbfaTzLPK tx9Q== X-Gm-Message-State: AOJu0Yz4kolv/uyJ8Bp8sk2gYgDIwOvV1/m6aDlfRCHy1mmWEVYmsgWF so5DZPX/BCkpdcDGlqzqd8tz1S3j5o82jP3vzXqu6+5TMpxz26KILKSZrtGMdTBtAUs= X-Gm-Gg: ASbGnctx2c0oZE45WXroLogKyOK4TM/k3oxguxD9qBhfxhIDoSsB9r8q7b6ZOS/dZCg TDIGbjV8tHC5kgJe7t6geRPjFw+xF5ZrZIBPihWPpWuHyxqvEFkCJIjumggnWvdsj+ItWniKfpE 8HW+W/1g+svPlWkhroMHutVgm+3NOxQSZtV4YEldV01XHSINjrC138FQxY4iVA0lJSIVDzk9iPJ w+XOXr8p6Bk88yFD7qk6wzLIyPOY6uY0ZPRsNfBeB/PaOHDOPjj1eTIs30v+wUVwuqgefPay/+g ob/OmvHmT5+3lu4v2j2g/lqjVMUFodw/Jts0ux5Mx78nuJHITIk3nujcqs+wxZPj1rCOyb4MdtX RR4HkkkohdVjdlSK1sXyx5hk2Ub9ZuJqKb5l9 X-Google-Smtp-Source: AGHT+IHHmj0O9tDskQVZYbGIP5I3afFV8mXIK7lX/bt8BOuo/P4E8r+t5rBS408HDHc9RZpvG4kNgw== X-Received: by 2002:a17:90b:5286:b0:312:959:dc41 with SMTP id 98e67ed59e1d1-3159d8d836cmr1315588a91.27.1750374999989; Thu, 19 Jun 2025 16:16:39 -0700 (PDT) Received: from russell-shotover-arch (222-152-91-9-vdsl.sparkbb.co.nz. [222.152.91.9]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-3158a2f3358sm3151478a91.30.2025.06.19.16.16.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Jun 2025 16:16:39 -0700 (PDT) From: russellgreene8-at-gmail.com@ffmpeg.org To: ffmpeg-devel@ffmpeg.org Date: Fri, 20 Jun 2025 11:15:59 +1200 Message-ID: <20250619231605.181423-1-russellgreene8@gmail.com> X-Mailer: git-send-email 2.50.0 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v2] hwcontext_vulkan: fix exporting multi-plane DRM modifiers X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Russell Greene Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: From: Russell Greene Previously, it was assumed that `drmFormatModifierPlaneCount` was one for all modifiers when exporting, which is not always the case, in particular for AMD GPUs and maybe others. Fetch the number of memory planes and fill the structs appropriately in this situation. The encoded stream is still bad in the case whre modifers are involved, but I think this patch still stands on its own and I suspect that may be a driver bug. A potential improvement that could be make is to cache the format information, so we can avoid the two GetPhysicalDeviceFormatProperties2 calls for each export, as well as the allocation. I doubt this is very expensive, but seemed worth noting. v2 changes: query the format properties with the test image created in `vulkan_frames_init` to avoid allocating space for the query during export Signed-off-by: Russell Greene --- libavutil/hwcontext_vulkan.c | 104 +++++++++++++++++++++++++++++++---- 1 file changed, 94 insertions(+), 10 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index edff89af26..c51c66ba63 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -169,6 +169,9 @@ typedef struct VulkanFramesPriv { /* Modifier info list to free at uninit */ VkImageDrmFormatModifierListCreateInfoEXT *modifier_info; + + /* Properties for DRM modifier for each plane in the image */ + VkDrmFormatModifierPropertiesEXT drm_format_modifier_properties[5]; } VulkanFramesPriv; typedef struct AVVkFrameInternal { @@ -2772,7 +2775,9 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc) VulkanFramesPriv *fp = hwfc->hwctx; AVVulkanFramesContext *hwctx = &fp->p; VulkanDevicePriv *p = hwfc->device_ctx->hwctx; + AVVulkanDeviceContext *dev_hwctx = &p->p; VkImageUsageFlagBits supported_usage; + FFVulkanFunctions *vk = &p->vkctx.vkfn; const struct FFVkFormatEntry *fmt; int disable_multiplane = p->disable_multiplane || (hwctx->flags & AV_VK_FRAME_FLAG_DISABLE_MULTIPLANE); @@ -2912,6 +2917,63 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc) if (err) return err; + /* Collect `VkDrmFormatModifierPropertiesEXT` for each plane. Required for DRM export. */ + if (p->vkctx.extensions & FF_VK_EXT_DRM_MODIFIER_FLAGS && hwctx->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) { + VkImageDrmFormatModifierPropertiesEXT drm_mod = { + .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT, + }; + err = vk->GetImageDrmFormatModifierPropertiesEXT(dev_hwctx->act_dev, f->img[0], + &drm_mod); + if (err != VK_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to get image DRM format modifier properties"); + vulkan_frame_free(hwfc, f); + return AVERROR_EXTERNAL; + } + for (int i = 0; i < fmt->vk_planes; ++i) { + VkDrmFormatModifierPropertiesListEXT modp; + VkFormatProperties2 fmtp; + VkDrmFormatModifierPropertiesEXT *mod_props = NULL; + + modp = (VkDrmFormatModifierPropertiesListEXT) { + .sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT, + }; + fmtp = (VkFormatProperties2) { + .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2, + .pNext = &modp, + }; + + /* query drmFormatModifierCount by keeping pDrmFormatModifierProperties NULL */ + vk->GetPhysicalDeviceFormatProperties2(dev_hwctx->phys_dev, fmt->fallback[i], &fmtp); + + modp.pDrmFormatModifierProperties = + av_calloc(modp.drmFormatModifierCount, sizeof(*modp.pDrmFormatModifierProperties)); + if (!modp.pDrmFormatModifierProperties) { + vulkan_frame_free(hwfc, f); + return AVERROR(ENOMEM); + } + vk->GetPhysicalDeviceFormatProperties2(dev_hwctx->phys_dev, fmt->fallback[i], &fmtp); + + for (uint32_t i = 0; i < modp.drmFormatModifierCount; ++i) { + VkDrmFormatModifierPropertiesEXT *m = &modp.pDrmFormatModifierProperties[i]; + if (m->drmFormatModifier == drm_mod.drmFormatModifier) { + mod_props = m; + break; + } + } + + if (mod_props == NULL) { + av_log(hwfc, AV_LOG_ERROR, "No DRM format modifier properties found for modifier 0x%016lx\n", + drm_mod.drmFormatModifier); + av_free(modp.pDrmFormatModifierProperties); + vulkan_frame_free(hwfc, f); + return AVERROR_EXTERNAL; + } + + fp->drm_format_modifier_properties[i] = *mod_props; + av_free(modp.pDrmFormatModifierProperties); + } + } + vulkan_frame_free(hwfc, f); /* If user did not specify a pool, hwfc->pool will be set to the internal one @@ -3842,6 +3904,17 @@ static inline uint32_t vulkan_fmt_to_drm(VkFormat vkfmt) return DRM_FORMAT_INVALID; } +#define MAX_MEMORY_PLANES 4 +static VkImageAspectFlags plane_index_to_aspect(int plane) { + if (plane == 0) return VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT; + if (plane == 1) return VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT; + if (plane == 2) return VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT; + if (plane == 3) return VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT; + + av_assert2 (false && "Invalid plane index"); + return VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT; +} + static int vulkan_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags) { @@ -3910,14 +3983,29 @@ static int vulkan_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, drm_desc->nb_layers = planes; for (int i = 0; i < drm_desc->nb_layers; i++) { - VkSubresourceLayout layout; - VkImageSubresource sub = { - .aspectMask = VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT, - }; VkFormat plane_vkfmt = av_vkfmt_from_pixfmt(hwfc->sw_format)[i]; - drm_desc->layers[i].format = vulkan_fmt_to_drm(plane_vkfmt); - drm_desc->layers[i].nb_planes = 1; + drm_desc->layers[i].format = vulkan_fmt_to_drm(plane_vkfmt); + drm_desc->layers[i].nb_planes = fp->drm_format_modifier_properties[i].drmFormatModifierPlaneCount; + + if (drm_desc->layers[i].nb_planes > MAX_MEMORY_PLANES) { + av_log(hwfc, AV_LOG_ERROR, "Too many memory planes for DRM format!\n"); + err = AVERROR_EXTERNAL; + goto end; + } + + for (int j = 0; j < drm_desc->layers[i].nb_planes; j++) { + VkSubresourceLayout layout; + VkImageSubresource sub = { + .aspectMask = plane_index_to_aspect(j), + }; + + drm_desc->layers[i].planes[j].object_index = FFMIN(i, drm_desc->nb_objects - 1); + + vk->GetImageSubresourceLayout(hwctx->act_dev, f->img[i], &sub, &layout); + drm_desc->layers[i].planes[j].offset = layout.offset; + drm_desc->layers[i].planes[j].pitch = layout.rowPitch; + } if (drm_desc->layers[i].format == DRM_FORMAT_INVALID) { av_log(hwfc, AV_LOG_ERROR, "Cannot map to DRM layer, unsupported!\n"); @@ -3925,14 +4013,10 @@ static int vulkan_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, goto end; } - drm_desc->layers[i].planes[0].object_index = FFMIN(i, drm_desc->nb_objects - 1); if (f->tiling == VK_IMAGE_TILING_OPTIMAL) continue; - vk->GetImageSubresourceLayout(hwctx->act_dev, f->img[i], &sub, &layout); - drm_desc->layers[i].planes[0].offset = layout.offset; - drm_desc->layers[i].planes[0].pitch = layout.rowPitch; } dst->width = src->width; -- 2.50.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".