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 0CE584D44F for ; Mon, 2 Jun 2025 00:34:10 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTP id 2A5F968D521; Mon, 2 Jun 2025 03:34:07 +0300 (EEST) Received: from MEUPR01CU001.outbound.protection.outlook.com (mail-australiasoutheastazolkn19010014.outbound.protection.outlook.com [52.103.73.14]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTPS id 1B1B568D51E for ; Mon, 2 Jun 2025 03:34:00 +0300 (EEST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=O+fR8dIIGHEgNQHgfF4o3BUUY0y6nRzBcC/SWnlvU+VTuo8c4C4sMSFzsFf7byrLtH6x7JFRtCkY25t8sgdudFyj0miP04Noo+IvvGFX7BOq4s3Sd2B6LweCBZOGVP489s1Ljk+wuTgz5Y+RvfUoA47hOFmfjZzDuc09NWjUkLXVvYSfcUgMmV4qJvFwTbQgW4c/N/HVbQFAprCh2pEGx0qHtJPpYgpk6/Uqk/T1mwyWDmiw1BDBe8fp7gg20gzqo2Pz+imz7teVIedY63otgf0KE2zq4NyJnwAiNj970EkGiSkqZXLUSuwIvtO2e92igFH6WBowt2lgFD5gA+o8Jw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=f1Z7yXfbatMnTo9IE+rI8tZCnJ/MWu5lhv9AVlaIMls=; b=Wn/Ad9TViUWN9NTGvXbBj504YA6eQ/LKRgLWPvs/fx66yk2oFaC32cptu+aCeEZf5EkcwIeEnMwMJQqtq2UcPhWq4XxlGmvquLaN2RHwXtx9DM204JpIYAFC0dN2hznh03G4uPBVHR07vb/31KgXwu+Gii8tA1t4E+QrCiRDrKSDxDk6heijcRGH/Jnjum5WzEpXN0W0Kd0s5idkwDeJAtAvKrs33cMQgzJu2h95O/Nrr6EUpFuMHObteuI5wJUMYqs5CM56UAW/KnIU4TY0BJeplYyeJ09hpOe/mPjH0NJcLBV68L4pKUmzmGfkvIor4H0aEOgXxLg5GXx2pZcEZA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=outlook.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=f1Z7yXfbatMnTo9IE+rI8tZCnJ/MWu5lhv9AVlaIMls=; b=NYbCHLjWAYsoIV2usrltAkqnJ9G4jImq5u731XhQ9+tfPZL7bJ767au2tk8PAmYiKeoOGOLuusoN+w54VkL4aZADy0j+ETWgLarYFKyKEi3F/xlZ+EuG0SFHTNNK0YCz1dvJNqAKxu9VSOZeJ+pILTf2JoKGNvg87NL/WGWzEcLh+myGO5D5DsiuZNxQbKQnirrkLmqRanJKcnhD8UEp9fLyPGXNBvvnmGgTwM/65jiFljAM2xouXih1eE4xhBt5jOTEGrdUx8oWyzIFdRjXJk7tMmR2mC7kL7gTypwmFkEjrp9M0yofQ+jrzlcyw85Y0CqT5qzCeuRmsDV7+cC56Q== Received: from SY7P300MB0845.AUSP300.PROD.OUTLOOK.COM (2603:10c6:10:288::12) by SY7P300MB0009.AUSP300.PROD.OUTLOOK.COM (2603:10c6:10:219::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8769.37; Mon, 2 Jun 2025 00:33:54 +0000 Received: from SY7P300MB0845.AUSP300.PROD.OUTLOOK.COM ([fe80::eaec:d3ce:9584:3e10]) by SY7P300MB0845.AUSP300.PROD.OUTLOOK.COM ([fe80::eaec:d3ce:9584:3e10%5]) with mapi id 15.20.8769.038; Mon, 2 Jun 2025 00:33:54 +0000 From: Tong Wu To: FFmpeg development discussions and patches Thread-Topic: [FFmpeg-devel] [PATCH, v3] avcodec/d3d12va_encode: texture array support for HEVC Thread-Index: AQHbzI833gtmCq5WBke4iIaqZ9WKN7PvDu9A Date: Mon, 2 Jun 2025 00:33:54 +0000 Message-ID: References: <20250524093511.1283-1-Primeadvice@gmail.com> In-Reply-To: <20250524093511.1283-1-Primeadvice@gmail.com> Accept-Language: en-US, zh-CN Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-messagesentrepresentingtype: 1 x-ms-publictraffictype: Email x-ms-traffictypediagnostic: SY7P300MB0845:EE_|SY7P300MB0009:EE_ x-ms-office365-filtering-correlation-id: 277a3eda-d624-409f-fe05-08dda16d277f x-microsoft-antispam: BCL:0; ARA:14566002|461199028|7092599006|15080799009|8060799009|8062599006|41001999006|19110799006|440099028|3412199025|102099032|12091999003|56899033; x-microsoft-antispam-message-info: =?us-ascii?Q?H76quMWszFxbzpQEuubFMIYspT/s4dH341hMNKLpIG9yh6rUMzbpO82Qfd26?= =?us-ascii?Q?G5JvUU0FOAVTZ/OfV0fQyT6xBCL28oxtx6aX1qlXaN/u0BRK1IKNMI5hsskx?= =?us-ascii?Q?WmpA7wGFtDJiCSiswN9Fu00nl/ocklXZuxC8DS7MNUxA0q1KfDJzu1twSa25?= =?us-ascii?Q?trmKkYST2NoYFhezVRIBTbNafkoH3Mh2Bt1G4OJwaVV/bYCbu4+oeyQkTEZJ?= =?us-ascii?Q?PAcJgDaZDEnXyI6dNHGLG6ll8oafZJ1TI1zB78ro8KDeMGbtwtzkdaFngbbq?= =?us-ascii?Q?Z7gVsUX/k5Cz+LJfBw9KmRn3gqCqO0xXrC9c+0Rh0qrxGN0yl1lqdq7YikE2?= =?us-ascii?Q?dmIWMtdTXQmj+aV9UM891nyW/3V3gJQazeAS6mDGBiy2VPNa4KJ717tzzl4x?= =?us-ascii?Q?7DHNy6olDua7XqBQszVFwmJYiyk/KmYsb+bzRse4qrd81miPrNAX2YyjvObh?= =?us-ascii?Q?E3TRi8YTQdrgwvR4cwY0raGsR1p8J9uaXXUtieENojzgIW2B/3oyLfLvbxka?= =?us-ascii?Q?bUTkQ+x2K0YedGh2Vg+Czpe98iKoO9i4m0TlMCoB0iAtpM30aWLjo6nimZwu?= =?us-ascii?Q?ls5zjTxetua5eXjk/4AnoiKXD12eTvOkzPl4mjC3SEsFY1R/80WEda8Q+5Jd?= =?us-ascii?Q?aXLPLJi38lw74e8FyKsHL+77ykVG6f7b0rnSaMdQq5fSX7VBf6+8ZvXR/Wyx?= =?us-ascii?Q?AIw/aG12dT2NzzK+hdhmxDL6Bt9MqVu1/5H5ewW/F4xhmfEVR8tFedQWjRKT?= =?us-ascii?Q?p8k2GtQdGuFi3W2uJdF7aejQrhlp7QvJB5zXPvs2vPacUt5pdzqiS2JQxkKz?= =?us-ascii?Q?SUhHzgrAj5PxB2gqMY/SSm3lXxbspGwYWl5bpysCEfovhAI3KeaH38CluQw8?= =?us-ascii?Q?VJKOAWKxlXOIlcb0GvlTiMtRJunqXpsNFxwwvfbVFkOJoYY50r3RHs6ny9kY?= =?us-ascii?Q?hv+TNV9lVXE2n7v7juU5c+f8MthBXH25TlsZpsT6tTYXMf+Z8jrwUdbiQxgU?= =?us-ascii?Q?lYU6R8+j6hPx91AmYOVzIt3BwtuNSaKCmELwKgWz36U3993/Nt5+HK6pMqVi?= =?us-ascii?Q?h2CaExuZyiZ7oZBj4EOweTkD/I0HrBdKpq7O0SQ+z6Gyl2OE5vwBF5uguVZC?= =?us-ascii?Q?KXdcW7VYtm6wD24FYU9hktaudPuIi46N0cto4fJiKTBPPp+G2Sirq3U=3D?= x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?eQ3saZVz8Wwwrhwo/OVpA1+wmxVit6K6FuWBG72TyXx2oGjm9TSTrxJOpSDF?= =?us-ascii?Q?nIWCYsg1bDK0c7TBc8UAk1lGpJnMb5b4JjEQYxmIXVvQRUGaT5yXZ67m42N9?= =?us-ascii?Q?3SIwqFUtC91ViPENm41Rz4EYvGiCjtk+Gr2rKraHugmQ2izwU3fsuQo/rRGS?= =?us-ascii?Q?6703HUzhxyBZB6RPTuwGyswO290JLxp3vYu6Pb3NLwN5FWMA3sYnDyS/aklp?= =?us-ascii?Q?ML6h/Xx4DPtNKY3R5sLHzuhsSUEAVyCEOaZLXpHEEjKCnODtBaDiJ56AbDtB?= =?us-ascii?Q?ycvqK3CHJysT3SUcypgImaL/Poq7GfBNfEPboLs6YN/Te7wFqHKG+yv7K1/m?= =?us-ascii?Q?xiO8j27WFw+adIr0ZM3hvRRyaEnpP/5M+oO6oLzsfy5dQmMz+3oIEyowmaF8?= =?us-ascii?Q?sD41ke9oX0cFrnuas06sAqKOW1E3gUmdm47qbwjTrH7F8kbpnwEW4FZA/FJI?= =?us-ascii?Q?Lh1CxVSNWg8J+BelJeIPxf5euGZtl4K26S3E+kST7v8KVU9szlMkIkF9YaaL?= =?us-ascii?Q?rMnRZ1iTZyjh49eNHT1eCgZV8XdsO2HgOimO/wnUDw2KGht8XcfLBAmS/gF+?= =?us-ascii?Q?Ie7ToXTMqxJY7SVyTY2xA5kbtHo+IPaocB5mt+jATLFAoGig/1dos+csOaTx?= =?us-ascii?Q?e4BPhvk/zztWHmJSxkkuF2xOvWTNd0Kz9woO+ZWz61IbSOaTKQ78ElmbqaVn?= =?us-ascii?Q?DL6oEOM3yWZnqWfZZNLPtho/U0U66KCsEy3WxGAvwYq5OTtnTF1+BThq3Uw0?= =?us-ascii?Q?x2teqDsLhjUU4/cnDn/nlp7e/yyioIq6ai4oUIfwr0SOssON7vkXhEuQtByT?= =?us-ascii?Q?uWI8nYXADtwn8ufH4pA/MEku57q4iUYIhU8SIRm6aruteKCeDxZOoQPd3EOi?= =?us-ascii?Q?H6eCpScCHWzQcQwlAAHH1/NICT0yJy/h5f/CggiiV42Y0gxqInctfoqSM8N3?= =?us-ascii?Q?hdz+26GOxzWD4uxZqKDl0XP+TGi/ur4lKN0qJofGoITPSjy+bWOysr7VQIjo?= =?us-ascii?Q?kZv4Z/whZ2HDb9PwguXtFqgFdsDljIXEMagiwxS/bjDYeSy6KxjfEp7l3Ybv?= =?us-ascii?Q?DH1IPHPj8Pv2PscWpqHt2S+hdrgFRFWFBR/ifi8HGr3E71ukanzhCO3+1O6J?= =?us-ascii?Q?29CFoq+Ey+rK2I0pwrDGXCG24DfPksZeg/tD+5LYlcJSi+EVQfoKSXi9Ab4J?= =?us-ascii?Q?+Gp5D0GCt3qEKYmoi+OrlZU4s2gpnl3FdCvSMyKPaQhY+xY+CFJ7jOLtXzQ?= =?us-ascii?Q?=3D?= MIME-Version: 1.0 X-OriginatorOrg: outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: SY7P300MB0845.AUSP300.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-CrossTenant-Network-Message-Id: 277a3eda-d624-409f-fe05-08dda16d277f X-MS-Exchange-CrossTenant-originalarrivaltime: 02 Jun 2025 00:33:54.2291 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-rms-persistedconsumerorg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: SY7P300MB0009 Subject: Re: [FFmpeg-devel] [PATCH, v3] avcodec/d3d12va_encode: texture array support for HEVC 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: Araz Iusubov 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: Araz Iusubov: > From: ffmpeg-devel On Behalf Of Araz > Iusubov > Sent: Saturday, May 24, 2025 5:35 PM > To: ffmpeg-devel@ffmpeg.org > Cc: Araz Iusubov > Subject: [FFmpeg-devel] [PATCH, v3] avcodec/d3d12va_encode: texture array > support for HEVC > > This patch adds support for the texture array feature used by AMD boards in the > D3D12 HEVC encoder. > In texture array mode, a single texture array is shared for all reference and > reconstructed pictures using different subresources. > The implementation ensures compatibility and has been successfully tested on > AMD, Intel, and NVIDIA GPUs. > > v2 updates: > 1. The reference to MaxL1ReferencesForB for the H.264 codec was updated to > use the corresponding H.264 field instead of the HEVC one. > 2. Max_subresource_array_size calculation was adjusted by removing the > D3D12VA_VIDEO_ENC_ASYNC_DEPTH offset. > > v3 updates: > 1. Fixed a type mismatch by explicitly casting AVD3D12VAFrame* to > (uint8_t*) when assigning to data[0]. > 2. Adjusted logging format specifier for HRESULT to use `%lx`. > > --- > libavcodec/d3d12va_encode.c | 241 +++++++++++++++++++++++++------ > libavcodec/d3d12va_encode.h | 29 ++++ > libavcodec/d3d12va_encode_hevc.c | 5 +- > 3 files changed, 231 insertions(+), 44 deletions(-) > > diff --git a/libavcodec/d3d12va_encode.c b/libavcodec/d3d12va_encode.c index > 4d738200fe..85e79b2e14 100644 > --- a/libavcodec/d3d12va_encode.c > +++ b/libavcodec/d3d12va_encode.c > @@ -264,6 +264,11 @@ static int d3d12va_encode_issue(AVCodecContext > *avctx, > > av_log(avctx, AV_LOG_DEBUG, "Input surface is %p.\n", pic->input_surface- > >texture); > > + if (ctx->is_texture_array) { > + base_pic->recon_image->data[0] = (uint8_t *)ctx->texture_array_frame; This does not look right. base_pic->recon_image is matained by frame pool. If you just overwrite it, the original memory will be lost. > + pic->subresource_index = (ctx->subresource_used_index++) % ctx- > >max_subresource_array_size; > + } > + > pic->recon_surface = (AVD3D12VAFrame *)base_pic->recon_image->data[0]; > av_log(avctx, AV_LOG_DEBUG, "Recon surface is %p.\n", > pic->recon_surface->texture); @@ -325,11 +330,28 @@ static int > d3d12va_encode_issue(AVCodecContext *avctx, > goto fail; > } > > + if (ctx->is_texture_array) { > + d3d12_refs.pSubresources = av_calloc(d3d12_refs.NumTexture2Ds, > + sizeof(*d3d12_refs.pSubresources)); > + if (!d3d12_refs.pSubresources) { > + err = AVERROR(ENOMEM); > + goto fail; > + } > + } > + > i = 0; > - for (j = 0; j < base_pic->nb_refs[0]; j++) > - d3d12_refs.ppTexture2Ds[i++] = ((D3D12VAEncodePicture *)base_pic- > >refs[0][j]->priv)->recon_surface->texture; > - for (j = 0; j < base_pic->nb_refs[1]; j++) > - d3d12_refs.ppTexture2Ds[i++] = ((D3D12VAEncodePicture *)base_pic- > >refs[1][j]->priv)->recon_surface->texture; > + for (j = 0; j < base_pic->nb_refs[0]; j++) { > + d3d12_refs.ppTexture2Ds[i] = ((D3D12VAEncodePicture *)base_pic- > >refs[0][j]->priv)->recon_surface->texture; > + if (ctx->is_texture_array) > + d3d12_refs.pSubresources[i] = ((D3D12VAEncodePicture *)base_pic- > >refs[0][j]->priv)->subresource_index; > + i++; > + } > + for (j = 0; j < base_pic->nb_refs[1]; j++) { > + d3d12_refs.ppTexture2Ds[i] = ((D3D12VAEncodePicture *)base_pic- > >refs[1][j]->priv)->recon_surface->texture; > + if (ctx->is_texture_array) > + d3d12_refs.pSubresources[i] = ((D3D12VAEncodePicture *)base_pic- > >refs[1][j]->priv)->subresource_index; > + i++; > + } > } > > input_args.PictureControlDesc.IntraRefreshFrameIndex = 0; @@ -343,7 > +365,11 @@ static int d3d12va_encode_issue(AVCodecContext *avctx, > output_args.Bitstream.pBuffer = pic->output_buffer; > output_args.Bitstream.FrameStartOffset = pic- > >aligned_header_size; > output_args.ReconstructedPicture.pReconstructedPicture = pic- > >recon_surface->texture; > - output_args.ReconstructedPicture.ReconstructedPictureSubresource = 0; > + if (ctx->is_texture_array) { > + output_args.ReconstructedPicture.ReconstructedPictureSubresource = pic- > >subresource_index; > + } else { > + output_args.ReconstructedPicture.ReconstructedPictureSubresource = 0; > + } > output_args.EncoderOutputMetadata.pBuffer = pic- > >encoded_metadata; > output_args.EncoderOutputMetadata.Offset = 0; > > @@ -381,35 +407,87 @@ static int d3d12va_encode_issue(AVCodecContext > *avctx, > }, \ > } > > +#define TRANSITION_BARRIER_SUBRESOURCE(res, subres,before, after) \ > + (D3D12_RESOURCE_BARRIER) { \ > + .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, \ > + .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE, \ > + .Transition = { \ > + .pResource = res, \ > + .Subresource = subres, \ > + .StateBefore = before, \ > + .StateAfter = after, \ > + }, \ > + } > + Looks like you could rewrite the original TRANSITION_BARRIER instead of adding a new one. > barriers[0] = TRANSITION_BARRIER(pic->input_surface->texture, > D3D12_RESOURCE_STATE_COMMON, > D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ); > barriers[1] = TRANSITION_BARRIER(pic->output_buffer, > D3D12_RESOURCE_STATE_COMMON, > D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE); > - barriers[2] = TRANSITION_BARRIER(pic->recon_surface->texture, > + barriers[2] = TRANSITION_BARRIER(pic->encoded_metadata, > D3D12_RESOURCE_STATE_COMMON, > D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE); > - barriers[3] = TRANSITION_BARRIER(pic->encoded_metadata, > + barriers[3] = TRANSITION_BARRIER(pic->resolved_metadata, > D3D12_RESOURCE_STATE_COMMON, > D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE); > - barriers[4] = TRANSITION_BARRIER(pic->resolved_metadata, > - D3D12_RESOURCE_STATE_COMMON, > - D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE); > - > - ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, 5, barriers); > - > - if (d3d12_refs.NumTexture2Ds) { > - D3D12_RESOURCE_BARRIER refs_barriers[3]; > - > - for (i = 0; i < d3d12_refs.NumTexture2Ds; i++) > - refs_barriers[i] = TRANSITION_BARRIER(d3d12_refs.ppTexture2Ds[i], > - D3D12_RESOURCE_STATE_COMMON, > - D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ); > - > - ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, > d3d12_refs.NumTexture2Ds, > - refs_barriers); > + ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, 4, > + barriers); > + > + //set transit barriers for reference pic and recon pic > + int barriers_ref_index = 0; > + D3D12_RESOURCE_BARRIER *barriers_ref = NULL; > + if (ctx->is_texture_array) { > + barriers_ref = av_calloc(ctx->max_subresource_array_size * ctx- > >plane_count, > + sizeof(D3D12_RESOURCE_BARRIER)); > + } else { > + barriers_ref = > av_calloc(MAX_DPB_SIZE,sizeof(D3D12_RESOURCE_BARRIER)); > + } > + > + if (ctx->is_texture_array) { > + // In Texture array mode, the D3D12 uses the same texture array for all the > input > + // reference pics in ppTexture2Ds and also for the pReconstructedPicture > output allocations, > + //just different subresources. > + D3D12_RESOURCE_DESC references_tex_array_desc = { 0 }; > + > + pic->recon_surface->texture->lpVtbl->GetDesc(pic->recon_surface->textu > + re, &references_tex_array_desc); > + > + for (uint32_t reference_subresource = 0; reference_subresource < > references_tex_array_desc.DepthOrArraySize; > + reference_subresource++) { > + > + //D3D12 DecomposeSubresource > + uint32_t mip_slice, plane_slice, array_slice, array_size; > + array_size = references_tex_array_desc.DepthOrArraySize; > + mip_slice = reference_subresource % > references_tex_array_desc.MipLevels; > + array_slice = (reference_subresource / > + references_tex_array_desc.MipLevels) % array_size; > + > + for (plane_slice = 0; plane_slice < ctx->plane_count; plane_slice++) { > + //Calculate the subresource index > + uint32_t planeOutputSubresource = mip_slice + array_slice * > references_tex_array_desc.MipLevels + > + plane_slice * > + references_tex_array_desc.MipLevels * array_size; > + > + if (reference_subresource == pic->subresource_index) { > + barriers_ref[barriers_ref_index++] = > TRANSITION_BARRIER_SUBRESOURCE(pic->recon_surface->texture, > planeOutputSubresource, > + D3D12_RESOURCE_STATE_COMMON, > + D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE); > + } else { > + barriers_ref[barriers_ref_index++] = > TRANSITION_BARRIER_SUBRESOURCE(pic->recon_surface->texture, > planeOutputSubresource, > + D3D12_RESOURCE_STATE_COMMON, > + D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ); > + } > + } > + } > + } else { > + barriers_ref[barriers_ref_index++] = TRANSITION_BARRIER(pic- > >recon_surface->texture, > + D3D12_RESOURCE_STATE_COMMON, > + > + D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE); > + > + if (d3d12_refs.NumTexture2Ds) { > + for (i = 0; i < d3d12_refs.NumTexture2Ds; i++) > + barriers_ref[barriers_ref_index++] = > TRANSITION_BARRIER(d3d12_refs.ppTexture2Ds[i], > + D3D12_RESOURCE_STATE_COMMON, > + > D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ); > + } > } > + ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, > + barriers_ref_index, barriers_ref); > > ID3D12VideoEncodeCommandList2_EncodeFrame(cmd_list, ctx->encoder, ctx- > >encoder_heap, > &input_args, &output_args); @@ -422,16 +500,15 @@ > static int d3d12va_encode_issue(AVCodecContext *avctx, > > > ID3D12VideoEncodeCommandList2_ResolveEncoderOutputMetadata(cmd_list, > &input_metadata, &output_metadata); > > - if (d3d12_refs.NumTexture2Ds) { > - D3D12_RESOURCE_BARRIER refs_barriers[3]; > - > - for (i = 0; i < d3d12_refs.NumTexture2Ds; i++) > - refs_barriers[i] = TRANSITION_BARRIER(d3d12_refs.ppTexture2Ds[i], > - D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ, > - D3D12_RESOURCE_STATE_COMMON); > - > - ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, > d3d12_refs.NumTexture2Ds, > - refs_barriers); > + //swap the barriers_ref transition state > + if (barriers_ref_index > 0) { > + for (i = 0; i < barriers_ref_index; i++) { > + D3D12_RESOURCE_STATES temp_statue = > barriers_ref[i].Transition.StateBefore; > + barriers_ref[i].Transition.StateBefore = > barriers_ref[i].Transition.StateAfter; > + barriers_ref[i].Transition.StateAfter = temp_statue; > + } > + ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, > barriers_ref_index, > + barriers_ref); > } > > barriers[0] = TRANSITION_BARRIER(pic->input_surface->texture, > @@ -440,17 +517,14 @@ static int d3d12va_encode_issue(AVCodecContext > *avctx, > barriers[1] = TRANSITION_BARRIER(pic->output_buffer, > D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE, > D3D12_RESOURCE_STATE_COMMON); > - barriers[2] = TRANSITION_BARRIER(pic->recon_surface->texture, > - D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE, > - D3D12_RESOURCE_STATE_COMMON); > - barriers[3] = TRANSITION_BARRIER(pic->encoded_metadata, > + barriers[2] = TRANSITION_BARRIER(pic->encoded_metadata, > D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ, > D3D12_RESOURCE_STATE_COMMON); > - barriers[4] = TRANSITION_BARRIER(pic->resolved_metadata, > + barriers[3] = TRANSITION_BARRIER(pic->resolved_metadata, > D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE, > D3D12_RESOURCE_STATE_COMMON); > > - ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, 5, barriers); > + ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, 4, > + barriers); > > hr = ID3D12VideoEncodeCommandList2_Close(cmd_list); > if (FAILED(hr)) { > @@ -489,6 +563,14 @@ static int d3d12va_encode_issue(AVCodecContext > *avctx, > if (d3d12_refs.ppTexture2Ds) > av_freep(&d3d12_refs.ppTexture2Ds); > > + if (ctx->is_texture_array) { > + if (d3d12_refs.pSubresources) > + av_freep(&d3d12_refs.pSubresources); > + } > + > + if (barriers_ref) > + av_freep(&barriers_ref); > + > return 0; > > fail: > @@ -498,6 +580,14 @@ fail: > if (d3d12_refs.ppTexture2Ds) > av_freep(&d3d12_refs.ppTexture2Ds); > > + if (ctx->is_texture_array) { > + if (d3d12_refs.pSubresources) > + av_freep(&d3d12_refs.pSubresources); > + } > + > + if (barriers_ref) > + av_freep(&barriers_ref); > + > if (ctx->codec->free_picture_params) > ctx->codec->free_picture_params(pic); > > @@ -1088,13 +1178,15 @@ static int > d3d12va_encode_init_gop_structure(AVCodecContext *avctx) > switch (ctx->codec->d3d12_codec) { > case D3D12_VIDEO_ENCODER_CODEC_H264: > ref_l0 = FFMIN(support.PictureSupport.pH264Support- > >MaxL0ReferencesForP, > - support.PictureSupport.pH264Support- > >MaxL1ReferencesForB); > + support.PictureSupport.pH264Support- > >MaxL1ReferencesForB ? > + > + support.PictureSupport.pH264Support->MaxL1ReferencesForB : UINT_MAX); > ref_l1 = support.PictureSupport.pH264Support->MaxL1ReferencesForB; > break; > > case D3D12_VIDEO_ENCODER_CODEC_HEVC: > ref_l0 = FFMIN(support.PictureSupport.pHEVCSupport- > >MaxL0ReferencesForP, > - support.PictureSupport.pHEVCSupport- > >MaxL1ReferencesForB); > + support.PictureSupport.pHEVCSupport- > >MaxL1ReferencesForB ? > + > + support.PictureSupport.pHEVCSupport->MaxL1ReferencesForB : UINT_MAX); > ref_l1 = support.PictureSupport.pHEVCSupport->MaxL1ReferencesForB; > break; > It seems to be another bugfix. If so please add it as a separate patch. > @@ -1336,6 +1428,47 @@ fail: > return err; > } > > +static int d3d12va_create_texture_array(AVHWFramesContext *ctx, > +D3D12VAEncodeContext *encode_context) { > + AVD3D12VAFramesContext *hwctx = ctx->hwctx; > + AVD3D12VADeviceContext *device_hwctx = ctx->device_ctx->hwctx; > + > + AVD3D12VAFrame *frame; > + D3D12_HEAP_PROPERTIES props = { .Type = D3D12_HEAP_TYPE_DEFAULT }; > + > + encode_context->max_subresource_array_size = MAX_DPB_SIZE + 1; > + > + D3D12_RESOURCE_DESC desc = { > + .Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D, > + .Alignment = 0, > + .Width = ctx->width, > + .Height = ctx->height, > + .DepthOrArraySize = encode_context->max_subresource_array_size, > + .MipLevels = 1, > + .Format = hwctx->format, > + .SampleDesc = {.Count = 1, .Quality = 0 }, > + .Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, > + .Flags = hwctx->flags, > + }; > + > + frame = av_mallocz(sizeof(AVD3D12VAFrame)); > + if (!frame) > + return AVERROR(ENOMEM); > + > + if (FAILED(ID3D12Device_CreateCommittedResource(device_hwctx->device, > &props, D3D12_HEAP_FLAG_NONE, &desc, > + D3D12_RESOURCE_STATE_COMMON, NULL, &IID_ID3D12Resource, (void > **)&frame->texture))) { > + av_log(ctx, AV_LOG_ERROR, "Could not create the texture\n"); > + return AVERROR(EINVAL); > + } > + > + ID3D12Device_CreateFence(device_hwctx->device, 0, > D3D12_FENCE_FLAG_NONE, > + &IID_ID3D12Fence, (void > + **)&frame->sync_ctx.fence); > + > + frame->sync_ctx.event = CreateEvent(NULL, FALSE, FALSE, NULL); > + encode_context->texture_array_frame = frame; > + return 0; > +} > + > static int d3d12va_encode_create_recon_frames(AVCodecContext *avctx) { > FFHWBaseEncodeContext *base_ctx = avctx->priv_data; @@ -1394,6 +1527,7 > @@ int ff_d3d12va_encode_init(AVCodecContext *avctx) > FFHWBaseEncodeContext *base_ctx = avctx->priv_data; > D3D12VAEncodeContext *ctx = avctx->priv_data; > D3D12_FEATURE_DATA_VIDEO_FEATURE_AREA_SUPPORT support = { 0 }; > + D3D12_FEATURE_DATA_FORMAT_INFO format_info = {0}; > int err; > HRESULT hr; > > @@ -1429,6 +1563,15 @@ int ff_d3d12va_encode_init(AVCodecContext *avctx) > goto fail; > } > > + format_info.Format = ((AVD3D12VAFramesContext*)base_ctx->input_frames- > >hwctx)->format; > + if (FAILED(ID3D12VideoDevice_CheckFeatureSupport(ctx->hwctx->device, > D3D12_FEATURE_FORMAT_INFO, > + &format_info, sizeof(format_info)))) { > + av_log(avctx, AV_LOG_ERROR, "Failed to query format plane count: > 0x%lx\n", hr); > + err = AVERROR_EXTERNAL; > + goto fail; > + } > + ctx->plane_count = format_info.PlaneCount; > + > err = d3d12va_encode_set_profile(avctx); > if (err < 0) > goto fail; > @@ -1485,6 +1628,10 @@ int ff_d3d12va_encode_init(AVCodecContext *avctx) > goto fail; > } > > + if (ctx->is_texture_array) { > + d3d12va_create_texture_array(base_ctx->recon_frames, avctx- > >priv_data); > + } > + You don't need too many arguments for this function. You could just feed avctx like any other functions here. > base_ctx->output_delay = base_ctx->b_per_p; > base_ctx->decode_delay = base_ctx->max_b_depth; > > @@ -1528,6 +1675,18 @@ int ff_d3d12va_encode_close(AVCodecContext > *avctx) > > av_buffer_pool_uninit(&ctx->output_buffer_pool); > > + if (ctx->is_texture_array) { > + ID3D12Resource *pResource = ctx->texture_array_frame->texture; > + if (pResource) { > + D3D12_OBJECT_RELEASE(pResource); > + ctx->texture_array_frame->texture = NULL; > + } > + D3D12_OBJECT_RELEASE(ctx->texture_array_frame->sync_ctx.fence); > + if (ctx->texture_array_frame->sync_ctx.event) > + CloseHandle(ctx->texture_array_frame->sync_ctx.event); > + av_free(ctx->texture_array_frame); > + } > + > D3D12_OBJECT_RELEASE(ctx->command_list); > D3D12_OBJECT_RELEASE(ctx->command_queue); > > diff --git a/libavcodec/d3d12va_encode.h b/libavcodec/d3d12va_encode.h index > 3b0b8153d5..fc31857f1a 100644 > --- a/libavcodec/d3d12va_encode.h > +++ b/libavcodec/d3d12va_encode.h > @@ -52,6 +52,8 @@ typedef struct D3D12VAEncodePicture { > ID3D12Resource *encoded_metadata; > ID3D12Resource *resolved_metadata; > > + int subresource_index; > + > D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA pic_ctl; > > int fence_value; > @@ -189,6 +191,33 @@ typedef struct D3D12VAEncodeContext { > */ > AVBufferPool *output_buffer_pool; > > + /** > + * Flag indicates if the HW is texture array mode. > + */ > + int is_texture_array; > + > + /** > + * In texture array mode, the D3D12 uses the same texture array for all the > input > + * reference pics in ppTexture2Ds and also for the pReconstructedPicture > output > + * allocations, just different subresources. > + */ > + AVD3D12VAFrame *texture_array_frame; > + > + /** > + * The max number of subresources in the texture array. > + */ > + int max_subresource_array_size; > + > + /** > + * The used subresource index for pic in the texture array. > + */ > + int subresource_used_index; > + > + /** > + * The number of planes in the input DXGI FORMAT . > + */ > + int plane_count; > + > /** > * D3D12 video encoder. > */ > diff --git a/libavcodec/d3d12va_encode_hevc.c > b/libavcodec/d3d12va_encode_hevc.c > index 938ba01f54..7e1d973f7e 100644 > --- a/libavcodec/d3d12va_encode_hevc.c > +++ b/libavcodec/d3d12va_encode_hevc.c > @@ -280,9 +280,8 @@ static int > d3d12va_encode_hevc_init_sequence_params(AVCodecContext *avctx) > } > > if (support.SupportFlags & > D3D12_VIDEO_ENCODER_SUPPORT_FLAG_RECONSTRUCTED_FRAMES_REQUIR > E_TEXTURE_ARRAYS) { > - av_log(avctx, AV_LOG_ERROR, "D3D12 video encode on this device requires > texture array support, " > - "but it's not implemented.\n"); > - return AVERROR_PATCHWELCOME; > + ctx->is_texture_array = 1; > + av_log(avctx, AV_LOG_DEBUG, "D3D12 video encode on this device > + uses texture array mode.\n"); > } > > desc = av_pix_fmt_desc_get(base_ctx->input_frames->sw_format); > -- Again, thanks for the patch that enables texture array. However, I don't think it's a good idea that you create the texture here and overwrite the original memory which is allocated and maintained by frame pool. Could you please take a look at hwcontext_d3d11va to see how it handles both texture array and single texture. There's already a initial_pool_size variable to handle the situation where the pool does not support dynamic allocation. In my opinion, we could add same features to hwcontext_d3d12va to make it better. Regards, Tong _______________________________________________ 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".