xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/d3d12/d3d12_video_screen.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © Microsoft Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include "d3d12_screen.h"
25 #include "d3d12_video_screen.h"
26 #include "d3d12_format.h"
27 #include "util/u_video.h"
28 #include <directx/d3d12video.h>
29 #include <cmath>
30 
31 #include <wrl/client.h>
32 using Microsoft::WRL::ComPtr;
33 
34 #include "d3d12_video_types.h"
35 
36 struct d3d12_encode_codec_support {
37    enum pipe_video_profile profile;
38    union {
39       struct {
40          enum pipe_video_h264_enc_dbk_filter_mode_flags disable_dbk_filter_mode_flags;
41          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_H264 d3d12_caps;
42       } h264_support;
43       struct {
44          enum pipe_h265_enc_pred_direction prediction_direction;
45          union pipe_h265_enc_cap_features hevc_features;
46          union pipe_h265_enc_cap_block_sizes hevc_block_sizes;
47          union pipe_h265_enc_cap_range_extension hevc_range_ext;
48          union pipe_h265_enc_cap_range_extension_flags hevc_range_ext_flags;
49          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC1 d3d12_caps;
50       } hevc_support;
51       struct {
52          union pipe_av1_enc_cap_features features;
53          union pipe_av1_enc_cap_features_ext1 features_ext1;
54          union pipe_av1_enc_cap_features_ext2 features_ext2;
55          D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION_SUPPORT d3d12_caps;
56          D3D12_VIDEO_ENCODER_CODEC_AV1_PICTURE_CONTROL_SUPPORT d3d12_picture_control;
57       } av1_support;
58    };
59 };
60 
61 struct d3d12_video_resolution_to_level_mapping_entry
62 {
63    D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC resolution;
64    uint32_t level;
65 };
66 
67 static void
get_level_resolution_video_decode_support(D3D12_VIDEO_DECODE_CONFIGURATION decoderConfig,DXGI_FORMAT format,struct pipe_screen * pscreen,bool & outSupportAny,D3D12_FEATURE_DATA_VIDEO_DECODE_SUPPORT & outMaxSupportedConfig,d3d12_video_resolution_to_level_mapping_entry & outMaxResol,d3d12_video_resolution_to_level_mapping_entry & outMinResol)68 get_level_resolution_video_decode_support(D3D12_VIDEO_DECODE_CONFIGURATION decoderConfig,
69                                               DXGI_FORMAT format,
70                                               struct pipe_screen *pscreen,
71                                               bool &outSupportAny,
72                                               D3D12_FEATURE_DATA_VIDEO_DECODE_SUPPORT &outMaxSupportedConfig,
73                                               d3d12_video_resolution_to_level_mapping_entry &outMaxResol,
74                                               d3d12_video_resolution_to_level_mapping_entry &outMinResol)
75 {
76    outSupportAny = false;
77    outMaxSupportedConfig = {};
78    outMinResol = {};
79    outMaxResol = {};
80 
81    ComPtr<ID3D12VideoDevice> spD3D12VideoDevice;
82    struct d3d12_screen *pD3D12Screen = (struct d3d12_screen *) pscreen;
83    if (FAILED(pD3D12Screen->dev->QueryInterface(IID_PPV_ARGS(spD3D12VideoDevice.GetAddressOf())))) {
84       // No video support in underlying d3d12 device (decode needs ID3D12VideoDevice)
85       return;
86    }
87 
88    d3d12_video_resolution_to_level_mapping_entry resolutionsLevelList[] = {
89       { { 8192, 4352 }, 61 },   // 8k
90       { { 8192, 4320 }, 61 },   // 8k
91       { { 7680, 4800 }, 61 },   // 8k - alternative
92       { { 7680, 4320 }, 61 },   // 8k - alternative
93       { { 4096, 2304 }, 52 },   // 2160p (4K)
94       { { 4096, 2160 }, 52 },   // 2160p (4K) - alternative
95       { { 2560, 1440 }, 51 },   // 1440p
96       { { 1920, 1200 }, 5 },    // 1200p
97       { { 1920, 1080 }, 42 },   // 1080p
98       { { 1280, 720 }, 4 },     // 720p
99       { { 800, 600 }, 31 },
100       { { 352, 480 }, 3 },
101       { { 352, 240 }, 2 },
102       { { 176, 144 }, 11 },
103       { { 128, 96 }, 11 },
104       { { 64, 64 }, 11 },
105    };
106 
107    D3D12_FEATURE_DATA_VIDEO_DECODE_SUPPORT decodeSupport = {};
108    decodeSupport.Configuration = decoderConfig;
109    decodeSupport.DecodeFormat = format;
110 
111    uint32_t idxResol = 0;
112    while (idxResol < ARRAY_SIZE(resolutionsLevelList)) {
113 
114       decodeSupport.Width = resolutionsLevelList[idxResol].resolution.Width;
115       decodeSupport.Height = resolutionsLevelList[idxResol].resolution.Height;
116 
117       if (SUCCEEDED(spD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_DECODE_SUPPORT,
118                                                             &decodeSupport,
119                                                             sizeof(decodeSupport)))) {
120          if (((decodeSupport.SupportFlags & D3D12_VIDEO_DECODE_SUPPORT_FLAG_SUPPORTED) != 0) ||
121              decodeSupport.DecodeTier > D3D12_VIDEO_DECODE_TIER_NOT_SUPPORTED) {
122 
123             // Save the first (maximum)
124             if(!outSupportAny) {
125                outMaxSupportedConfig = decodeSupport;
126                outMaxResol = resolutionsLevelList[idxResol];
127                outSupportAny = true;
128             }
129 
130             // Keep saving the other supported values to get the minimum
131             outMinResol = resolutionsLevelList[idxResol];
132          }
133       }
134       idxResol++;
135    }
136 }
137 
138 static bool
d3d12_has_video_decode_support(struct pipe_screen * pscreen,enum pipe_video_profile profile)139 d3d12_has_video_decode_support(struct pipe_screen *pscreen, enum pipe_video_profile profile)
140 {
141    ComPtr<ID3D12VideoDevice> spD3D12VideoDevice;
142    struct d3d12_screen *pD3D12Screen = (struct d3d12_screen *) pscreen;
143    if (FAILED(pD3D12Screen->dev->QueryInterface(IID_PPV_ARGS(spD3D12VideoDevice.GetAddressOf())))) {
144       // No video support in underlying d3d12 device (needs ID3D12VideoDevice)
145       return 0;
146    }
147 
148    D3D12_FEATURE_DATA_VIDEO_FEATURE_AREA_SUPPORT VideoFeatureAreaSupport = {};
149    if (FAILED(spD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_FEATURE_AREA_SUPPORT,
150                                                       &VideoFeatureAreaSupport,
151                                                       sizeof(VideoFeatureAreaSupport)))) {
152       return false;
153    }
154 
155    // Supported profiles below
156    bool supportsProfile = false;
157 #if D3D12_VIDEO_ANY_DECODER_ENABLED
158    switch (profile) {
159 #if VIDEO_CODEC_H264DEC
160       case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE:
161       case PIPE_VIDEO_PROFILE_MPEG4_AVC_EXTENDED:
162       case PIPE_VIDEO_PROFILE_MPEG4_AVC_CONSTRAINED_BASELINE:
163       case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN:
164       case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH:
165       case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH10:
166       {
167          supportsProfile = true;
168       } break;
169 #endif
170 #if VIDEO_CODEC_H265DEC
171       case PIPE_VIDEO_PROFILE_HEVC_MAIN:
172       case PIPE_VIDEO_PROFILE_HEVC_MAIN_10:
173       {
174          supportsProfile = true;
175       } break;
176 #endif
177 #if VIDEO_CODEC_AV1DEC
178       case PIPE_VIDEO_PROFILE_AV1_MAIN:
179       {
180          supportsProfile = true;
181       } break;
182 #endif
183 #if VIDEO_CODEC_VP9DEC
184       case PIPE_VIDEO_PROFILE_VP9_PROFILE0:
185       case PIPE_VIDEO_PROFILE_VP9_PROFILE2:
186       {
187          supportsProfile = true;
188       } break;
189 #endif
190       default:
191          supportsProfile = false;
192    }
193 #endif // D3D12_VIDEO_ANY_DECODER_ENABLED
194    return VideoFeatureAreaSupport.VideoDecodeSupport && supportsProfile;
195 }
196 
197 static bool
d3d12_video_encode_max_supported_level_for_profile(const D3D12_VIDEO_ENCODER_CODEC & argCodec,const D3D12_VIDEO_ENCODER_PROFILE_DESC & argTargetProfile,D3D12_VIDEO_ENCODER_LEVEL_SETTING & minLvl,D3D12_VIDEO_ENCODER_LEVEL_SETTING & maxLvl,ID3D12VideoDevice3 * pD3D12VideoDevice)198 d3d12_video_encode_max_supported_level_for_profile(const D3D12_VIDEO_ENCODER_CODEC &argCodec,
199                                                    const D3D12_VIDEO_ENCODER_PROFILE_DESC &argTargetProfile,
200                                                    D3D12_VIDEO_ENCODER_LEVEL_SETTING &minLvl,
201                                                    D3D12_VIDEO_ENCODER_LEVEL_SETTING &maxLvl,
202                                                    ID3D12VideoDevice3 *pD3D12VideoDevice)
203 {
204    D3D12_FEATURE_DATA_VIDEO_ENCODER_CODEC capCodecData = {};
205    capCodecData.NodeIndex = 0;
206    capCodecData.Codec = argCodec;
207    capCodecData.IsSupported = false;
208 
209    if ((FAILED(pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_CODEC,
210                                                      &capCodecData,
211                                                      sizeof(capCodecData))))
212                                                      || !capCodecData.IsSupported) {
213       return false;
214    }
215 
216    D3D12_FEATURE_DATA_VIDEO_ENCODER_PROFILE_LEVEL capLevelData = {};
217    capLevelData.NodeIndex = 0;
218    capLevelData.Codec = argCodec;
219    capLevelData.Profile = argTargetProfile;
220    capLevelData.MinSupportedLevel = minLvl;
221    capLevelData.MaxSupportedLevel = maxLvl;
222 
223    if (FAILED(pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_PROFILE_LEVEL,
224                                                      &capLevelData,
225                                                      sizeof(capLevelData)))) {
226       return false;
227    }
228 
229    return capLevelData.IsSupported;
230 }
231 
232 static bool
d3d12_video_encode_supported_resolution_range(const D3D12_VIDEO_ENCODER_CODEC & argTargetCodec,D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC & minResolution,D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC & maxResolution,union pipe_enc_cap_surface_alignment & alignment,ID3D12VideoDevice3 * pD3D12VideoDevice)233 d3d12_video_encode_supported_resolution_range(const D3D12_VIDEO_ENCODER_CODEC &argTargetCodec,
234                                               D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC &minResolution,
235                                               D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC &maxResolution,
236                                               union pipe_enc_cap_surface_alignment& alignment,
237                                               ID3D12VideoDevice3 *pD3D12VideoDevice)
238 {
239    D3D12_FEATURE_DATA_VIDEO_ENCODER_OUTPUT_RESOLUTION_RATIOS_COUNT capResRatiosCountData = { 0, argTargetCodec, 0 };
240 
241    if (FAILED(pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_OUTPUT_RESOLUTION_RATIOS_COUNT,
242                                                      &capResRatiosCountData,
243                                                      sizeof(capResRatiosCountData)))) {
244       return false;
245    }
246 
247    D3D12_FEATURE_DATA_VIDEO_ENCODER_OUTPUT_RESOLUTION capOutputResolutionData = {};
248    capOutputResolutionData.NodeIndex = 0;
249    capOutputResolutionData.Codec = argTargetCodec;
250    capOutputResolutionData.ResolutionRatiosCount = capResRatiosCountData.ResolutionRatiosCount;
251 
252    std::vector<D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_RATIO_DESC> ratiosTmpOutput;
253    if (capResRatiosCountData.ResolutionRatiosCount > 0) {
254       ratiosTmpOutput.resize(capResRatiosCountData.ResolutionRatiosCount);
255       capOutputResolutionData.pResolutionRatios = ratiosTmpOutput.data();
256    } else {
257       capOutputResolutionData.pResolutionRatios = nullptr;
258    }
259 
260    if (FAILED(pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_OUTPUT_RESOLUTION,
261                                                      &capOutputResolutionData,
262                                                      sizeof(capOutputResolutionData))) ||
263        !capOutputResolutionData.IsSupported) {
264       return false;
265    }
266 
267    minResolution = capOutputResolutionData.MinResolutionSupported;
268    maxResolution = capOutputResolutionData.MaxResolutionSupported;
269    alignment.bits.log2_width_alignment = std::log2(capOutputResolutionData.ResolutionWidthMultipleRequirement);
270    alignment.bits.log2_height_alignment = std::log2(capOutputResolutionData.ResolutionHeightMultipleRequirement);
271 
272    return true;
273 }
274 
275 static uint32_t
d3d12_video_encode_supported_references_per_frame_structures(const D3D12_VIDEO_ENCODER_CODEC & codec,D3D12_VIDEO_ENCODER_PROFILE_DESC profile,ID3D12VideoDevice3 * pD3D12VideoDevice,struct d3d12_encode_codec_support & codecSupport)276 d3d12_video_encode_supported_references_per_frame_structures(const D3D12_VIDEO_ENCODER_CODEC &codec,
277                                                              D3D12_VIDEO_ENCODER_PROFILE_DESC profile,
278                                                              ID3D12VideoDevice3 *pD3D12VideoDevice,
279                                                              struct d3d12_encode_codec_support& codecSupport)
280 {
281    uint32_t supportedMaxRefFrames = 0u;
282 
283    D3D12_FEATURE_DATA_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT capPictureControlData = {};
284    capPictureControlData.NodeIndex = 0;
285    capPictureControlData.Codec = codec;
286 
287    if(codec == D3D12_VIDEO_ENCODER_CODEC_H264) {
288       D3D12_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT_H264 h264PictureControl = {};
289       capPictureControlData.Profile = profile;
290       capPictureControlData.PictureSupport.pH264Support = &h264PictureControl;
291       capPictureControlData.PictureSupport.DataSize = sizeof(h264PictureControl);
292       HRESULT hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT,
293                                                             &capPictureControlData,
294                                                             sizeof(capPictureControlData));
295       if (FAILED(hr)) {
296          debug_printf("CheckFeatureSupport failed with HR %x\n", hr);
297       }
298 
299       if (capPictureControlData.IsSupported) {
300          /* This attribute determines the maximum number of reference
301          * frames supported for encoding.
302          *
303          * Note: for H.264 encoding, the value represents the maximum number
304          * of reference frames for both the reference picture list 0 (bottom
305          * 16 bits) and the reference picture list 1 (top 16 bits).
306          */
307          uint32_t MaxL0ReferencesForB = capPictureControlData.PictureSupport.pH264Support->MaxL0ReferencesForB;
308          uint32_t maxRefForL0 = std::min(capPictureControlData.PictureSupport.pH264Support->MaxL0ReferencesForP,
309                                          MaxL0ReferencesForB ? MaxL0ReferencesForB : UINT_MAX);
310          uint32_t maxRefForL1 = capPictureControlData.PictureSupport.pH264Support->MaxL1ReferencesForB;
311          supportedMaxRefFrames = (maxRefForL0 & 0xffff) | ((maxRefForL1 & 0xffff) << 16);
312       }
313    } else if(codec == D3D12_VIDEO_ENCODER_CODEC_HEVC) {
314       D3D12_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT_HEVC hevcPictureControl = {};
315       capPictureControlData.Profile = profile;
316       capPictureControlData.PictureSupport.pHEVCSupport = &hevcPictureControl;
317       capPictureControlData.PictureSupport.DataSize = sizeof(hevcPictureControl);
318       HRESULT hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT,
319                                                             &capPictureControlData,
320                                                             sizeof(capPictureControlData));
321       if (FAILED(hr)) {
322          debug_printf("CheckFeatureSupport failed with HR %x\n", hr);
323       }
324 
325       if (capPictureControlData.IsSupported) {
326          /* This attribute determines the maximum number of reference
327          * frames supported for encoding.
328          *
329          * Note: for H.265 encoding, the value represents the maximum number
330          * of reference frames for both the reference picture list 0 (bottom
331          * 16 bits) and the reference picture list 1 (top 16 bits).
332          */
333          uint32_t MaxL0ReferencesForB = capPictureControlData.PictureSupport.pHEVCSupport->MaxL0ReferencesForB;
334          uint32_t maxRefForL0 = std::min(capPictureControlData.PictureSupport.pHEVCSupport->MaxL0ReferencesForP,
335                                          MaxL0ReferencesForB ? MaxL0ReferencesForB : UINT_MAX);
336          uint32_t maxRefForL1 = capPictureControlData.PictureSupport.pHEVCSupport->MaxL1ReferencesForB;
337          supportedMaxRefFrames = (maxRefForL0 & 0xffff) | ((maxRefForL1 & 0xffff) << 16);
338       }
339    }
340    else if(codec == D3D12_VIDEO_ENCODER_CODEC_AV1){
341       codecSupport.av1_support.d3d12_picture_control = {};
342       capPictureControlData.Profile = profile;
343       capPictureControlData.PictureSupport.pAV1Support = &codecSupport.av1_support.d3d12_picture_control;
344       capPictureControlData.PictureSupport.DataSize = sizeof(codecSupport.av1_support.d3d12_picture_control);
345       HRESULT hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT,
346                                                             &capPictureControlData,
347                                                             sizeof(capPictureControlData));
348       if (FAILED(hr)) {
349          debug_printf("CheckFeatureSupport failed with HR %x\n", hr);
350       }
351 
352       if (capPictureControlData.IsSupported) {
353          /* This attribute determines the maximum number of reference
354          * frames supported for encoding.
355          */
356          supportedMaxRefFrames = capPictureControlData.PictureSupport.pAV1Support->MaxUniqueReferencesPerFrame;
357          if (capPictureControlData.PictureSupport.pAV1Support->PredictionMode)
358             supportedMaxRefFrames = (supportedMaxRefFrames & 0xffff) | ((supportedMaxRefFrames & 0xffff) << 16);
359       }
360    }
361    return supportedMaxRefFrames;
362 }
363 
364 static void
d3d12_video_encode_supported_tile_structures(const D3D12_VIDEO_ENCODER_CODEC & codec,const D3D12_VIDEO_ENCODER_PROFILE_DESC & profile,const D3D12_VIDEO_ENCODER_LEVEL_SETTING & level,ID3D12VideoDevice3 * pD3D12VideoDevice,D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC maxRes,uint32_t & supportedSliceStructures,D3D12_VIDEO_ENCODER_AV1_FRAME_SUBREGION_LAYOUT_CONFIG_SUPPORT & av1TileSupport)365 d3d12_video_encode_supported_tile_structures(const D3D12_VIDEO_ENCODER_CODEC &codec,
366                                              const D3D12_VIDEO_ENCODER_PROFILE_DESC &profile,
367                                              const D3D12_VIDEO_ENCODER_LEVEL_SETTING &level,
368                                              ID3D12VideoDevice3 *pD3D12VideoDevice,
369                                              D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC maxRes,
370                                              uint32_t& supportedSliceStructures, // out
371                                              D3D12_VIDEO_ENCODER_AV1_FRAME_SUBREGION_LAYOUT_CONFIG_SUPPORT& av1TileSupport // out
372 )
373 {
374    // Assume no support and then add as queries succeed
375    supportedSliceStructures = PIPE_VIDEO_CAP_SLICE_STRUCTURE_NONE;
376 
377    // Only codecs supporting tiles should use this method. For slices related info, use d3d12_video_encode_supported_slice_structures
378    assert (codec == D3D12_VIDEO_ENCODER_CODEC_AV1);
379 
380    D3D12_FEATURE_DATA_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_CONFIG capDataTilesSupport = { };
381    capDataTilesSupport.NodeIndex = 0;
382    capDataTilesSupport.Codec = codec;
383    capDataTilesSupport.Profile = profile;
384    capDataTilesSupport.Level = level;
385    capDataTilesSupport.FrameResolution = maxRes; // Query for worst case resolution
386    av1TileSupport = { };
387    capDataTilesSupport.CodecSupport.DataSize = sizeof(av1TileSupport);
388    capDataTilesSupport.CodecSupport.pAV1Support = &av1TileSupport;
389    av1TileSupport.Use128SuperBlocks = false; // return units in 64x64 default size
390    constexpr UINT superBlockSize = 64u;
391 
392    {
393       capDataTilesSupport.SubregionMode = D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_GRID_PARTITION;
394       // Try with simple one tile request
395       av1TileSupport.TilesConfiguration.ColCount = 1;
396       av1TileSupport.TilesConfiguration.RowCount = 1;
397       av1TileSupport.TilesConfiguration.ColWidths[0] = (capDataTilesSupport.FrameResolution.Width / superBlockSize);
398       av1TileSupport.TilesConfiguration.RowHeights[0] = (capDataTilesSupport.FrameResolution.Height / superBlockSize);
399       HRESULT hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_CONFIG,
400                                                   &capDataTilesSupport,
401                                                   sizeof(capDataTilesSupport));
402       if(SUCCEEDED(hr) && !capDataTilesSupport.IsSupported) {
403          // Try with minimum driver indicated params for the given resolution
404          // (ie. this could happen for high resolutions like 8K where AV1 max_tile_width (4096) is exceeded)
405          av1TileSupport.TilesConfiguration.ColCount = std::max(av1TileSupport.MinTileCols, 1u);
406          av1TileSupport.TilesConfiguration.RowCount = std::max(av1TileSupport.MinTileRows, 1u);
407          hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_CONFIG,
408                                                   &capDataTilesSupport,
409                                                   sizeof(capDataTilesSupport));
410       }
411 
412       // Try with lower resolution as fallback
413       D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC fallbackRes = { 1920u, 1080u };
414       if(SUCCEEDED(hr) && !capDataTilesSupport.IsSupported && (fallbackRes.Width <= maxRes.Width)
415         && (fallbackRes.Height <= maxRes.Height) ) {
416          auto oldRes = capDataTilesSupport.FrameResolution;
417          capDataTilesSupport.FrameResolution = fallbackRes;
418          hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_CONFIG,
419                                                   &capDataTilesSupport,
420                                                   sizeof(capDataTilesSupport));
421          capDataTilesSupport.FrameResolution = oldRes;
422       }
423 
424       if(SUCCEEDED(hr) && capDataTilesSupport.IsSupported)
425          supportedSliceStructures |= (PIPE_VIDEO_CAP_SLICE_STRUCTURE_POWER_OF_TWO_ROWS |
426                                       PIPE_VIDEO_CAP_SLICE_STRUCTURE_EQUAL_ROWS |
427                                       PIPE_VIDEO_CAP_SLICE_STRUCTURE_EQUAL_MULTI_ROWS);
428    }
429 
430    {
431       capDataTilesSupport.SubregionMode = D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_CONFIGURABLE_GRID_PARTITION;
432       // Try with simple one tile request
433       av1TileSupport.TilesConfiguration.ColCount = 1;
434       av1TileSupport.TilesConfiguration.RowCount = 1;
435       av1TileSupport.TilesConfiguration.ColWidths[0] = capDataTilesSupport.FrameResolution.Width;
436       av1TileSupport.TilesConfiguration.RowHeights[0] = capDataTilesSupport.FrameResolution.Height;
437       HRESULT hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_CONFIG,
438                                                   &capDataTilesSupport,
439                                                   sizeof(capDataTilesSupport));
440       if(SUCCEEDED(hr) && !capDataTilesSupport.IsSupported) {
441          // Try with minimum driver indicated params for the given resolution
442          // (ie. this could happen for high resolutions like 8K where AV1 max_tile_width (4096) is exceeded)
443          av1TileSupport.TilesConfiguration.ColCount = std::max(av1TileSupport.MinTileCols, 1u);
444          av1TileSupport.TilesConfiguration.RowCount = std::max(av1TileSupport.MinTileRows, 1u);
445          // Try for uniform grid tiles
446          UINT tileWPixel = capDataTilesSupport.FrameResolution.Width / av1TileSupport.TilesConfiguration.ColCount;
447          UINT tileHPixel = capDataTilesSupport.FrameResolution.Height / av1TileSupport.TilesConfiguration.RowCount;
448          for (UINT i = 0; i < av1TileSupport.TilesConfiguration.ColCount; i++)
449             av1TileSupport.TilesConfiguration.ColWidths[i] = (tileWPixel / superBlockSize);
450          for (UINT j = 0; j < av1TileSupport.TilesConfiguration.RowCount; j++)
451             av1TileSupport.TilesConfiguration.RowHeights[j] = (tileHPixel / superBlockSize);
452 
453          hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_CONFIG,
454                                                   &capDataTilesSupport,
455                                                   sizeof(capDataTilesSupport));
456       }
457 
458       if(SUCCEEDED(hr) && capDataTilesSupport.IsSupported)
459          supportedSliceStructures |= (PIPE_VIDEO_CAP_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS |
460                                       PIPE_VIDEO_CAP_SLICE_STRUCTURE_ARBITRARY_ROWS);
461    }
462 }
463 
464 static uint32_t
d3d12_video_encode_supported_slice_structures(const D3D12_VIDEO_ENCODER_CODEC & codec,D3D12_VIDEO_ENCODER_PROFILE_DESC profile,D3D12_VIDEO_ENCODER_LEVEL_SETTING level,ID3D12VideoDevice3 * pD3D12VideoDevice)465 d3d12_video_encode_supported_slice_structures(const D3D12_VIDEO_ENCODER_CODEC &codec,
466                                               D3D12_VIDEO_ENCODER_PROFILE_DESC profile,
467                                               D3D12_VIDEO_ENCODER_LEVEL_SETTING level,
468                                               ID3D12VideoDevice3 *pD3D12VideoDevice)
469 {
470    // Only codecs supporting slices should use this method. For tile related info, use d3d12_video_encode_supported_tile_structures
471    assert ((codec == D3D12_VIDEO_ENCODER_CODEC_H264) || (codec == D3D12_VIDEO_ENCODER_CODEC_HEVC));
472 
473    uint32_t supportedSliceStructuresBitMask = PIPE_VIDEO_CAP_SLICE_STRUCTURE_NONE;
474 
475    D3D12_FEATURE_DATA_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE capDataSubregionLayout = {};
476    capDataSubregionLayout.NodeIndex = 0;
477    capDataSubregionLayout.Codec = codec;
478    capDataSubregionLayout.Profile = profile;
479    capDataSubregionLayout.Level = level;
480 
481    /**
482     * pipe_video_cap_slice_structure
483     *
484     * This attribute determines slice structures supported by the
485     * driver for encoding. This attribute is a hint to the user so
486     * that he can choose a suitable surface size and how to arrange
487     * the encoding process of multiple slices per frame.
488     *
489     * More specifically, for H.264 encoding, this attribute
490     * determines the range of accepted values to
491     * h264_slice_descriptor::macroblock_address and
492     * h264_slice_descriptor::num_macroblocks.
493     *
494     * For HEVC, similarly determines the ranges for
495     * slice_segment_address
496     * num_ctu_in_slice
497     */
498    capDataSubregionLayout.SubregionMode =
499       D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_PARTITIONING_SUBREGIONS_PER_FRAME;
500    HRESULT hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE,
501                                                        &capDataSubregionLayout,
502                                                        sizeof(capDataSubregionLayout));
503    if (FAILED(hr)) {
504       debug_printf("CheckFeatureSupport failed with HR %x\n", hr);
505    } else if (capDataSubregionLayout.IsSupported) {
506       /* This would be setting N subregions per frame in this D3D12 mode where N = (height/blocksize) / K */
507       supportedSliceStructuresBitMask |= PIPE_VIDEO_CAP_SLICE_STRUCTURE_EQUAL_MULTI_ROWS;
508       /* Assuming height/blocksize >= max_supported_slices, which is reported
509       in PIPE_VIDEO_CAP_ENC_MAX_SLICES_PER_FRAME and should be checked by the client*/
510       /* This would be setting N subregions per frame in this D3D12 mode where N = (height/blocksize) */
511       supportedSliceStructuresBitMask |= PIPE_VIDEO_CAP_SLICE_STRUCTURE_EQUAL_ROWS;
512       /* This is ok, would be setting K rows per subregions in this D3D12 mode (and rounding the last one) */
513       supportedSliceStructuresBitMask |= PIPE_VIDEO_CAP_SLICE_STRUCTURE_POWER_OF_TWO_ROWS;
514    }
515 
516    capDataSubregionLayout.SubregionMode =
517       D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_PARTITIONING_ROWS_PER_SUBREGION;
518    hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE,
519                                                          &capDataSubregionLayout,
520                                                          sizeof(capDataSubregionLayout));
521    if (FAILED(hr)) {
522       debug_printf("CheckFeatureSupport failed with HR %x\n", hr);
523    } else if (capDataSubregionLayout.IsSupported) {
524       /* This would be setting K rows per subregions in this D3D12 mode */
525       supportedSliceStructuresBitMask |= PIPE_VIDEO_CAP_SLICE_STRUCTURE_EQUAL_MULTI_ROWS;
526       /* Assuming height/blocksize >= max_supported_slices, which is reported
527       in PIPE_VIDEO_CAP_ENC_MAX_SLICES_PER_FRAME and should be checked by the client*/
528       /* This would be setting 1 row per subregion in this D3D12 mode */
529       supportedSliceStructuresBitMask |= PIPE_VIDEO_CAP_SLICE_STRUCTURE_EQUAL_ROWS;
530       /* This is ok, would be setting K rows per subregions in this D3D12 mode (and rounding the last one) */
531       supportedSliceStructuresBitMask |= PIPE_VIDEO_CAP_SLICE_STRUCTURE_POWER_OF_TWO_ROWS;
532    }
533 
534    capDataSubregionLayout.SubregionMode =
535       D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_SQUARE_UNITS_PER_SUBREGION_ROW_UNALIGNED;
536    hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE,
537                                                          &capDataSubregionLayout,
538                                                          sizeof(capDataSubregionLayout));
539    if (FAILED(hr)) {
540       debug_printf("CheckFeatureSupport failed with HR %x\n", hr);
541    } else if (capDataSubregionLayout.IsSupported) {
542       /* This would be setting K rows per subregions in this D3D12 mode */
543       supportedSliceStructuresBitMask |= PIPE_VIDEO_CAP_SLICE_STRUCTURE_EQUAL_MULTI_ROWS;
544       /* Assuming height/blocksize >= max_supported_slices, which is reported
545       in PIPE_VIDEO_CAP_ENC_MAX_SLICES_PER_FRAME and should be checked by the client*/
546       /* This would be setting 1 row per subregion in this D3D12 mode */
547       supportedSliceStructuresBitMask |= PIPE_VIDEO_CAP_SLICE_STRUCTURE_EQUAL_ROWS;
548       /* This is ok, would be setting K rows per subregions in this D3D12 mode (and rounding the last one) */
549       supportedSliceStructuresBitMask |= PIPE_VIDEO_CAP_SLICE_STRUCTURE_POWER_OF_TWO_ROWS;
550       /* This is ok, would be setting K MBs per subregions in this D3D12 mode*/
551       supportedSliceStructuresBitMask |= PIPE_VIDEO_CAP_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS;
552    }
553 
554    capDataSubregionLayout.SubregionMode = D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_BYTES_PER_SUBREGION;
555    hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE,
556                                                          &capDataSubregionLayout,
557                                                          sizeof(capDataSubregionLayout));
558    if (FAILED(hr)) {
559       debug_printf("CheckFeatureSupport failed with HR %x\n", hr);
560    } else if (capDataSubregionLayout.IsSupported) {
561       supportedSliceStructuresBitMask |= PIPE_VIDEO_CAP_SLICE_STRUCTURE_MAX_SLICE_SIZE;
562    }
563 
564    return supportedSliceStructuresBitMask;
565 }
566 
567 static bool
d3d12_video_encode_support_caps(const D3D12_VIDEO_ENCODER_CODEC & argTargetCodec,D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC maxResolution,DXGI_FORMAT encodeFormat,ID3D12VideoDevice3 * pD3D12VideoDevice,D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT codecSupport,D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT1 & capEncoderSupportData1,D3D12_FEATURE_DATA_VIDEO_ENCODER_RESOLUTION_SUPPORT_LIMITS & resolutionDepCaps,uint32_t & maxQualityLevels)568 d3d12_video_encode_support_caps(const D3D12_VIDEO_ENCODER_CODEC &argTargetCodec,
569                                 D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC maxResolution,
570                                 DXGI_FORMAT encodeFormat,
571                                 ID3D12VideoDevice3 *pD3D12VideoDevice,
572                                 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT codecSupport,
573                                 D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT1 &capEncoderSupportData1,
574                                 D3D12_FEATURE_DATA_VIDEO_ENCODER_RESOLUTION_SUPPORT_LIMITS &resolutionDepCaps,
575                                 uint32_t &maxQualityLevels)
576 {
577    capEncoderSupportData1.NodeIndex = 0;
578    capEncoderSupportData1.Codec = argTargetCodec;
579    capEncoderSupportData1.InputFormat = encodeFormat;
580    capEncoderSupportData1.RateControl = {};
581    capEncoderSupportData1.RateControl.Mode = D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CQP;
582    capEncoderSupportData1.RateControl.TargetFrameRate.Numerator = 60;
583    capEncoderSupportData1.RateControl.TargetFrameRate.Denominator = 1;
584    D3D12_VIDEO_ENCODER_RATE_CONTROL_CQP rcCqp = { 25, 25, 25 };
585    capEncoderSupportData1.RateControl.ConfigParams.pConfiguration_CQP = &rcCqp;
586    capEncoderSupportData1.RateControl.ConfigParams.DataSize = sizeof(rcCqp);
587    capEncoderSupportData1.IntraRefresh = D3D12_VIDEO_ENCODER_INTRA_REFRESH_MODE_NONE;
588    capEncoderSupportData1.ResolutionsListCount = 1;
589    capEncoderSupportData1.pResolutionList = &maxResolution;
590    capEncoderSupportData1.MaxReferenceFramesInDPB = 1;
591    /*
592       All codec structures must be declared outside the switch statement to be
593       present in memory (stack scope) when calling CheckFeatureSupport below
594    */
595    D3D12_VIDEO_ENCODER_PROFILE_H264 h264prof = {};
596    D3D12_VIDEO_ENCODER_LEVELS_H264 h264lvl = {};
597    D3D12_VIDEO_ENCODER_SEQUENCE_GOP_STRUCTURE_H264 h264Gop = { 1, 0, 0, 0, 0 };
598    D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264 h264Config = {};
599    D3D12_VIDEO_ENCODER_PROFILE_HEVC hevcprof = { };
600    D3D12_VIDEO_ENCODER_LEVEL_TIER_CONSTRAINTS_HEVC hevcLvl = { };
601    D3D12_VIDEO_ENCODER_SEQUENCE_GOP_STRUCTURE_HEVC hevcGop = { 1, 0, 0 };
602    D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC hevcConfig = {};
603    D3D12_VIDEO_ENCODER_AV1_PROFILE av1prof = { };
604    D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS av1Lvl = { };
605    D3D12_VIDEO_ENCODER_AV1_SEQUENCE_STRUCTURE av1Gop = { 1, 0 };
606    D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION av1Config = {};
607    switch (argTargetCodec) {
608       case D3D12_VIDEO_ENCODER_CODEC_H264:
609       {
610          // assert(codecSupport.pH264Support); // Fill this in caller if ever used
611          capEncoderSupportData1.SuggestedProfile.pH264Profile = &h264prof;
612          capEncoderSupportData1.SuggestedProfile.DataSize = sizeof(h264prof);
613          capEncoderSupportData1.SuggestedLevel.pH264LevelSetting = &h264lvl;
614          capEncoderSupportData1.SuggestedLevel.DataSize = sizeof(h264lvl);
615          capEncoderSupportData1.CodecGopSequence.pH264GroupOfPictures = &h264Gop;
616          capEncoderSupportData1.CodecGopSequence.DataSize = sizeof(h264Gop);
617          capEncoderSupportData1.CodecConfiguration.DataSize = sizeof(h264Config);
618          capEncoderSupportData1.CodecConfiguration.pH264Config = &h264Config;
619       } break;
620 
621       case D3D12_VIDEO_ENCODER_CODEC_HEVC:
622       {
623          /* Only read from codecSupport.pHEVCSupport in this case (union of pointers definition) */
624          assert(codecSupport.pHEVCSupport);
625          hevcConfig = {
626             D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_NONE,
627             codecSupport.pHEVCSupport->MinLumaCodingUnitSize,
628             codecSupport.pHEVCSupport->MaxLumaCodingUnitSize,
629             codecSupport.pHEVCSupport->MinLumaTransformUnitSize,
630             codecSupport.pHEVCSupport->MaxLumaTransformUnitSize,
631             codecSupport.pHEVCSupport->max_transform_hierarchy_depth_inter,
632             codecSupport.pHEVCSupport->max_transform_hierarchy_depth_intra,
633          };
634 
635          if ((codecSupport.pHEVCSupport->SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_ASYMETRIC_MOTION_PARTITION_REQUIRED) != 0)
636             hevcConfig.ConfigurationFlags |= D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_USE_ASYMETRIC_MOTION_PARTITION;
637 
638          capEncoderSupportData1.SuggestedProfile.pHEVCProfile = &hevcprof;
639          capEncoderSupportData1.SuggestedProfile.DataSize = sizeof(hevcprof);
640          capEncoderSupportData1.SuggestedLevel.pHEVCLevelSetting = &hevcLvl;
641          capEncoderSupportData1.SuggestedLevel.DataSize = sizeof(hevcLvl);
642          capEncoderSupportData1.CodecGopSequence.pHEVCGroupOfPictures = &hevcGop;
643          capEncoderSupportData1.CodecGopSequence.DataSize = sizeof(hevcGop);
644          capEncoderSupportData1.CodecConfiguration.DataSize = sizeof(hevcConfig);
645          capEncoderSupportData1.CodecConfiguration.pHEVCConfig = &hevcConfig;
646       } break;
647 
648       case D3D12_VIDEO_ENCODER_CODEC_AV1:
649       {
650          capEncoderSupportData1.SuggestedProfile.pAV1Profile = &av1prof;
651          capEncoderSupportData1.SuggestedProfile.DataSize = sizeof(av1prof);
652          capEncoderSupportData1.SuggestedLevel.pAV1LevelSetting = &av1Lvl;
653          capEncoderSupportData1.SuggestedLevel.DataSize = sizeof(av1Lvl);
654          capEncoderSupportData1.CodecGopSequence.pAV1SequenceStructure = &av1Gop;
655          capEncoderSupportData1.CodecGopSequence.DataSize = sizeof(av1Gop);
656          D3D12_FEATURE_DATA_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT capCodecConfigData = { };
657          capCodecConfigData.NodeIndex = 0;
658          capCodecConfigData.Codec = D3D12_VIDEO_ENCODER_CODEC_AV1;
659          capCodecConfigData.Profile.pAV1Profile = &av1prof;
660          capCodecConfigData.Profile.DataSize = sizeof(av1prof);
661          D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION_SUPPORT av1CodecSupport = { };
662          capCodecConfigData.CodecSupportLimits.pAV1Support = &av1CodecSupport;
663          capCodecConfigData.CodecSupportLimits.DataSize = sizeof(av1CodecSupport);
664          HRESULT hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT, &capCodecConfigData, sizeof(capCodecConfigData));
665          if (FAILED(hr)) {
666             debug_printf("CheckFeatureSupport D3D12_FEATURE_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT failed with HR %x\n", hr);
667             return false;
668          } else if (!capCodecConfigData.IsSupported) {
669             debug_printf("CheckFeatureSupport D3D12_FEATURE_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT IsSupported is false\n");
670             return false;
671          }
672          av1Config.OrderHintBitsMinus1 = 7;
673          av1Config.FeatureFlags = av1CodecSupport.RequiredFeatureFlags;
674          capEncoderSupportData1.CodecConfiguration.DataSize = sizeof(av1Config);
675          capEncoderSupportData1.CodecConfiguration.pAV1Config = &av1Config;
676       } break;
677       default:
678       {
679          unreachable("Unsupported D3D12_VIDEO_ENCODER_CODEC");
680       } break;
681    }
682 
683    // prepare inout storage for the resolution dependent result.
684    resolutionDepCaps = {};
685    capEncoderSupportData1.pResolutionDependentSupport = &resolutionDepCaps;
686 
687    HRESULT hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_SUPPORT1,
688                                                            &capEncoderSupportData1,
689                                                            sizeof(capEncoderSupportData1));
690    if (FAILED(hr)) {
691       debug_printf("CheckFeatureSupport D3D12_FEATURE_VIDEO_ENCODER_SUPPORT1 failed with HR %x\n", hr);
692       debug_printf("Falling back to check previous query version D3D12_FEATURE_VIDEO_ENCODER_SUPPORT...\n");
693 
694       // D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT1 extends D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT
695       // in a binary compatible way, so just cast it and try with the older query D3D12_FEATURE_VIDEO_ENCODER_SUPPORT
696       D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT * casted_down_cap_data = reinterpret_cast<D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT*>(&capEncoderSupportData1);
697       hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_SUPPORT,
698                                                                          casted_down_cap_data,
699                                                                          sizeof(D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT));
700       if (FAILED(hr)) {
701          debug_printf("CheckFeatureSupport D3D12_FEATURE_VIDEO_ENCODER_SUPPORT failed with HR %x\n", hr);
702          return false;
703       }
704    }
705 
706    // Convert between D3D12 definition and PIPE definition
707 
708    // D3D12: QualityVsSpeed must be in the range [0, D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT1.MaxQualityVsSpeed]
709    // The lower the value, the fastest the encode operation
710 
711    // PIPE: The quality level range can be queried through the VAConfigAttribEncQualityRange attribute.
712    // A lower value means higher quality, and a value of 1 represents the highest quality.
713    // The quality level setting is used as a trade-off between quality and speed/power
714    // consumption, with higher quality corresponds to lower speed and higher power consumption.
715    maxQualityLevels = capEncoderSupportData1.MaxQualityVsSpeed + 1; // VA range starts from 1, D3D12 starts from 0
716 
717    bool configSupported =
718       (((capEncoderSupportData1.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_GENERAL_SUPPORT_OK) != 0) &&
719          (capEncoderSupportData1.ValidationFlags == D3D12_VIDEO_ENCODER_VALIDATION_FLAG_NONE));
720 
721    return configSupported;
722 }
723 
724 bool
d3d12_video_encode_get_av1_codec_support(const D3D12_VIDEO_ENCODER_CODEC & argCodec,const D3D12_VIDEO_ENCODER_PROFILE_DESC & argTargetProfile,ID3D12VideoDevice3 * pD3D12VideoDevice,D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION_SUPPORT & av1Support)725 static d3d12_video_encode_get_av1_codec_support ( const D3D12_VIDEO_ENCODER_CODEC &argCodec,
726                                                    const D3D12_VIDEO_ENCODER_PROFILE_DESC &argTargetProfile,
727                                                    ID3D12VideoDevice3 *pD3D12VideoDevice,
728                                                    D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION_SUPPORT &av1Support)
729 {
730    D3D12_FEATURE_DATA_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT capCodecConfigData = { };
731    capCodecConfigData.NodeIndex = 0;
732    capCodecConfigData.Codec = D3D12_VIDEO_ENCODER_CODEC_AV1;
733    capCodecConfigData.Profile = argTargetProfile;
734    capCodecConfigData.CodecSupportLimits.pAV1Support = &av1Support;
735    capCodecConfigData.CodecSupportLimits.DataSize = sizeof(D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION_SUPPORT);
736    if(SUCCEEDED(pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT, &capCodecConfigData, sizeof(capCodecConfigData)))
737       && capCodecConfigData.IsSupported) {
738          return true;
739    }
740 
741    memset(&av1Support, 0, sizeof(D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION_SUPPORT));
742    return false;
743 }
744 
745 bool
d3d12_video_encode_get_h264_codec_support(const D3D12_VIDEO_ENCODER_PROFILE_DESC & argTargetProfile,ID3D12VideoDevice3 * pD3D12VideoDevice,D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_H264 & supportedCaps)746 static d3d12_video_encode_get_h264_codec_support(const D3D12_VIDEO_ENCODER_PROFILE_DESC &argTargetProfile,
747                                                  ID3D12VideoDevice3 *pD3D12VideoDevice,
748                                                  D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_H264 &supportedCaps)
749 {
750    D3D12_FEATURE_DATA_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT capCodecConfigData = { };
751    capCodecConfigData.NodeIndex = 0;
752    capCodecConfigData.Codec = D3D12_VIDEO_ENCODER_CODEC_H264;
753    capCodecConfigData.Profile = argTargetProfile;
754    capCodecConfigData.CodecSupportLimits.pH264Support = &supportedCaps;
755    capCodecConfigData.CodecSupportLimits.DataSize = sizeof(supportedCaps);
756 
757    if(FAILED(pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT, &capCodecConfigData, sizeof(capCodecConfigData)))
758       || !capCodecConfigData.IsSupported)
759    {
760          debug_printf("D3D12_FEATURE_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT call failed.");
761          return false;
762    }
763 
764    return true;
765 }
766 
767 bool
d3d12_video_encode_get_hevc_codec_support(const D3D12_VIDEO_ENCODER_CODEC & argCodec,const D3D12_VIDEO_ENCODER_PROFILE_DESC & argTargetProfile,ID3D12VideoDevice3 * pD3D12VideoDevice,D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC1 & supportedCaps)768 static d3d12_video_encode_get_hevc_codec_support ( const D3D12_VIDEO_ENCODER_CODEC &argCodec,
769                                                    const D3D12_VIDEO_ENCODER_PROFILE_DESC &argTargetProfile,
770                                                    ID3D12VideoDevice3 *pD3D12VideoDevice,
771                                                    D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC1 &supportedCaps)
772 {
773    constexpr unsigned c_hevcConfigurationSets = 5u;
774    const D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC1 hevcConfigurationSets[c_hevcConfigurationSets] =
775    {
776       {
777          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_NONE,
778          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_8x8,
779          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_32x32,
780          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_4x4,
781          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_32x32,
782          3u,
783          3u,
784       },
785       {
786          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_NONE,
787          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_8x8,
788          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_32x32,
789          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_4x4,
790          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_32x32,
791          0u,
792          0u,
793       },
794       {
795          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_NONE,
796          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_8x8,
797          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_32x32,
798          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_4x4,
799          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_32x32,
800          2u,
801          2u,
802       },
803       {
804          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_NONE,
805          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_8x8,
806          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_64x64,
807          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_4x4,
808          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_32x32,
809          2u,
810          2u,
811       },
812       {
813          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_NONE,
814          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_8x8,
815          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_64x64,
816          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_4x4,
817          D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_32x32,
818          4u,
819          4u,
820       },
821    };
822 
823    D3D12_FEATURE_DATA_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT capCodecConfigData = { };
824    capCodecConfigData.NodeIndex = 0;
825    capCodecConfigData.Codec = D3D12_VIDEO_ENCODER_CODEC_HEVC;
826    capCodecConfigData.Profile = argTargetProfile;
827 
828    for (uint32_t i = 0 ; i < c_hevcConfigurationSets ; i++) {
829       supportedCaps = hevcConfigurationSets[i];
830       capCodecConfigData.CodecSupportLimits = ConvertHEVCSupportFromProfile((*capCodecConfigData.Profile.pHEVCProfile), &supportedCaps);
831       if(SUCCEEDED(pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT, &capCodecConfigData, sizeof(capCodecConfigData)))
832          && capCodecConfigData.IsSupported) {
833             return true;
834       }
835    }
836 
837    memset(&supportedCaps, 0, sizeof(D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC));
838    return false;
839 }
840 
841 static bool
d3d12_has_video_encode_support(struct pipe_screen * pscreen,enum pipe_video_profile profile,uint32_t & maxLvlSpec,D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC & minRes,D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC & maxRes,union pipe_enc_cap_surface_alignment & alignRes,uint32_t & maxSlices,uint32_t & supportedSliceStructures,uint32_t & maxReferencesPerFrame,struct d3d12_encode_codec_support & codecSupport,uint32_t & isRCMaxFrameSizeSupported,uint32_t & maxQualityLevels,uint32_t & max_tile_rows,uint32_t & max_tile_cols,uint32_t & maxIRDuration,union pipe_enc_cap_roi & roi_support)842 d3d12_has_video_encode_support(struct pipe_screen *pscreen,
843                                enum pipe_video_profile profile,
844                                uint32_t &maxLvlSpec,
845                                D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC &minRes,
846                                D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC &maxRes,
847                                union pipe_enc_cap_surface_alignment &alignRes,
848                                uint32_t &maxSlices,
849                                uint32_t &supportedSliceStructures,
850                                uint32_t &maxReferencesPerFrame,
851                                struct d3d12_encode_codec_support& codecSupport,
852                                uint32_t &isRCMaxFrameSizeSupported,
853                                uint32_t &maxQualityLevels,
854                                uint32_t &max_tile_rows,
855                                uint32_t &max_tile_cols,
856                                uint32_t &maxIRDuration,
857                                union pipe_enc_cap_roi &roi_support)
858 {
859    ComPtr<ID3D12VideoDevice3> spD3D12VideoDevice;
860    struct d3d12_screen *pD3D12Screen = (struct d3d12_screen *) pscreen;
861    if (FAILED(pD3D12Screen->dev->QueryInterface(IID_PPV_ARGS(spD3D12VideoDevice.GetAddressOf())))) {
862       // No video encode support in underlying d3d12 device (needs ID3D12VideoDevice3)
863       return 0;
864    }
865 
866    D3D12_FEATURE_DATA_VIDEO_FEATURE_AREA_SUPPORT VideoFeatureAreaSupport = {};
867    if (FAILED(spD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_FEATURE_AREA_SUPPORT,
868                                                       &VideoFeatureAreaSupport,
869                                                       sizeof(VideoFeatureAreaSupport)))) {
870       return false;
871    }
872    D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT d3d12_codec_support = { };
873    bool supportsProfile = false;
874    switch (profile) {
875 #if VIDEO_CODEC_H264ENC
876       case PIPE_VIDEO_PROFILE_MPEG4_AVC_CONSTRAINED_BASELINE:
877       case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE:
878       case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN:
879       case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH:
880       case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH10:
881       {
882          D3D12_VIDEO_ENCODER_PROFILE_DESC profDesc = {};
883          D3D12_VIDEO_ENCODER_PROFILE_H264 profH264 =
884             d3d12_video_encoder_convert_profile_to_d3d12_enc_profile_h264(profile);
885          profDesc.DataSize = sizeof(profH264);
886          profDesc.pH264Profile = &profH264;
887          D3D12_VIDEO_ENCODER_CODEC codecDesc = d3d12_video_encoder_convert_codec_to_d3d12_enc_codec(profile);
888          D3D12_VIDEO_ENCODER_LEVELS_H264 minLvlSettingH264 = static_cast<D3D12_VIDEO_ENCODER_LEVELS_H264>(0);
889          D3D12_VIDEO_ENCODER_LEVELS_H264 maxLvlSettingH264 = static_cast<D3D12_VIDEO_ENCODER_LEVELS_H264>(0);
890          D3D12_VIDEO_ENCODER_LEVEL_SETTING minLvl = {};
891          D3D12_VIDEO_ENCODER_LEVEL_SETTING maxLvl = {};
892          minLvl.pH264LevelSetting = &minLvlSettingH264;
893          minLvl.DataSize = sizeof(minLvlSettingH264);
894          maxLvl.pH264LevelSetting = &maxLvlSettingH264;
895          maxLvl.DataSize = sizeof(maxLvlSettingH264);
896          if (d3d12_video_encode_max_supported_level_for_profile(codecDesc,
897                                                                 profDesc,
898                                                                 minLvl,
899                                                                 maxLvl,
900                                                                 spD3D12VideoDevice.Get())) {
901             d3d12_video_encoder_convert_from_d3d12_level_h264(maxLvlSettingH264, maxLvlSpec);
902             supportsProfile = true;
903 
904             DXGI_FORMAT encodeFormat = d3d12_convert_pipe_video_profile_to_dxgi_format(profile);
905             supportsProfile = supportsProfile &&
906                               d3d12_video_encode_supported_resolution_range(codecDesc, minRes, maxRes, alignRes, spD3D12VideoDevice.Get());
907 
908             D3D12_VIDEO_ENCODER_PROFILE_DESC profile;
909             profile.pH264Profile = &profH264;
910             profile.DataSize = sizeof(profH264);
911             D3D12_VIDEO_ENCODER_LEVEL_SETTING level;
912             level.pH264LevelSetting = &maxLvlSettingH264;
913             level.DataSize = sizeof(maxLvlSettingH264);
914             supportedSliceStructures = d3d12_video_encode_supported_slice_structures(codecDesc,
915                                                                                      profile,
916                                                                                      level,
917                                                                                      spD3D12VideoDevice.Get());
918             D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT1 capEncoderSupportData1 = {};
919             D3D12_FEATURE_DATA_VIDEO_ENCODER_RESOLUTION_SUPPORT_LIMITS resolutionDepCaps;
920             capEncoderSupportData1.SubregionFrameEncoding = (supportedSliceStructures == PIPE_VIDEO_CAP_SLICE_STRUCTURE_NONE) ?
921                                                              D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_FULL_FRAME :
922                                                              D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_PARTITIONING_SUBREGIONS_PER_FRAME;
923             D3D12_VIDEO_ENCODER_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_SLICES sliceData = { };
924             capEncoderSupportData1.SubregionFrameEncodingData.DataSize = sizeof(sliceData);
925             capEncoderSupportData1.SubregionFrameEncodingData.pSlicesPartition_H264 = &sliceData;
926             supportsProfile = supportsProfile && d3d12_video_encode_support_caps(codecDesc,
927                                                                                  maxRes,
928                                                                                  encodeFormat,
929                                                                                  spD3D12VideoDevice.Get(),
930                                                                                  d3d12_codec_support,
931                                                                                  capEncoderSupportData1,
932                                                                                  resolutionDepCaps,
933                                                                                  maxQualityLevels);
934             if (supportedSliceStructures == PIPE_VIDEO_CAP_SLICE_STRUCTURE_NONE)
935                maxSlices = 0;
936             else
937                maxSlices = resolutionDepCaps.MaxSubregionsNumber;
938 
939             maxIRDuration = resolutionDepCaps.MaxIntraRefreshFrameDuration;
940             isRCMaxFrameSizeSupported = ((capEncoderSupportData1.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_RATE_CONTROL_MAX_FRAME_SIZE_AVAILABLE) != 0) ? 1 : 0;
941             maxReferencesPerFrame =
942                d3d12_video_encode_supported_references_per_frame_structures(codecDesc,
943                                                                             profile,
944                                                                             spD3D12VideoDevice.Get(),
945                                                                             codecSupport);
946 
947             memset(&roi_support, 0, sizeof(roi_support));
948             roi_support.bits.roi_rc_qp_delta_support = ((capEncoderSupportData1.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_RATE_CONTROL_DELTA_QP_AVAILABLE) != 0) ? 1 : 0;
949             roi_support.bits.num_roi_regions = roi_support.bits.roi_rc_qp_delta_support ? PIPE_ENC_ROI_REGION_NUM_MAX : 0;
950 
951             supportsProfile = d3d12_video_encode_get_h264_codec_support(profDesc,
952                                                                         spD3D12VideoDevice.Get(),
953                                                                         codecSupport.h264_support.d3d12_caps);
954          }
955       } break;
956 #endif
957 #if VIDEO_CODEC_H265ENC
958       case PIPE_VIDEO_PROFILE_HEVC_MAIN:
959       case PIPE_VIDEO_PROFILE_HEVC_MAIN_10:
960       case PIPE_VIDEO_PROFILE_HEVC_MAIN_444:
961       {
962          D3D12_VIDEO_ENCODER_PROFILE_DESC profDesc = {};
963          D3D12_VIDEO_ENCODER_PROFILE_HEVC profHEVC =
964             d3d12_video_encoder_convert_profile_to_d3d12_enc_profile_hevc(profile);
965          profDesc.DataSize = sizeof(profHEVC);
966          profDesc.pHEVCProfile = &profHEVC;
967          D3D12_VIDEO_ENCODER_CODEC codecDesc = d3d12_video_encoder_convert_codec_to_d3d12_enc_codec(profile);
968          D3D12_VIDEO_ENCODER_LEVEL_TIER_CONSTRAINTS_HEVC minLvlSettingHEVC = { };
969          D3D12_VIDEO_ENCODER_LEVEL_TIER_CONSTRAINTS_HEVC maxLvlSettingHEVC = { };
970          D3D12_VIDEO_ENCODER_LEVEL_SETTING minLvl = {};
971          D3D12_VIDEO_ENCODER_LEVEL_SETTING maxLvl = {};
972          minLvl.pHEVCLevelSetting = &minLvlSettingHEVC;
973          minLvl.DataSize = sizeof(minLvlSettingHEVC);
974          maxLvl.pHEVCLevelSetting = &maxLvlSettingHEVC;
975          maxLvl.DataSize = sizeof(maxLvlSettingHEVC);
976 
977          if (d3d12_video_encode_max_supported_level_for_profile(codecDesc,
978                                                                 profDesc,
979                                                                 minLvl,
980                                                                 maxLvl,
981                                                                 spD3D12VideoDevice.Get())) {
982             d3d12_video_encoder_convert_from_d3d12_level_hevc(maxLvlSettingHEVC.Level, maxLvlSpec);
983 
984             D3D12_VIDEO_ENCODER_PROFILE_DESC d3d12_profile;
985             d3d12_profile.pHEVCProfile = &profHEVC;
986             d3d12_profile.DataSize = sizeof(profHEVC);
987             D3D12_VIDEO_ENCODER_LEVEL_SETTING level;
988             level.pHEVCLevelSetting = &maxLvlSettingHEVC;
989             level.DataSize = sizeof(maxLvlSettingHEVC);
990             supportedSliceStructures = d3d12_video_encode_supported_slice_structures(codecDesc,
991                                                                                      d3d12_profile,
992                                                                                      level,
993                                                                                      spD3D12VideoDevice.Get());
994 
995             maxReferencesPerFrame =
996                d3d12_video_encode_supported_references_per_frame_structures(codecDesc,
997                                                                             d3d12_profile,
998                                                                             spD3D12VideoDevice.Get(),
999                                                                             codecSupport);
1000 
1001             supportsProfile = d3d12_video_encode_get_hevc_codec_support(codecDesc,
1002                                                                         profDesc,
1003                                                                         spD3D12VideoDevice.Get(),
1004                                                                         codecSupport.hevc_support.d3d12_caps);
1005             if (supportsProfile) {
1006                d3d12_codec_support.DataSize = sizeof(codecSupport.hevc_support.d3d12_caps);
1007                d3d12_codec_support.pHEVCSupport1 = &codecSupport.hevc_support.d3d12_caps;
1008 
1009                /* get_video_param sets pipe_features.bits.config_supported = 1
1010                   to distinguish between supported cap with all bits off and unsupported by driver
1011                   with value = 0
1012                */
1013                codecSupport.hevc_support.hevc_block_sizes.bits.config_supported = 1;
1014                codecSupport.hevc_support.hevc_features.bits.config_supported = 1;
1015 
1016                // Fill codecSupport.hevc_support
1017 
1018                uint8_t minCuSize = d3d12_video_encoder_convert_12cusize_to_pixel_size_hevc(codecSupport.hevc_support.d3d12_caps.MinLumaCodingUnitSize);
1019                uint8_t maxCuSize = d3d12_video_encoder_convert_12cusize_to_pixel_size_hevc(codecSupport.hevc_support.d3d12_caps.MaxLumaCodingUnitSize);
1020                uint8_t MinCbLog2SizeY = std::log2(minCuSize);
1021                uint8_t CtbLog2SizeY = std::log2(maxCuSize);
1022                uint8_t minTuSize = d3d12_video_encoder_convert_12tusize_to_pixel_size_hevc(codecSupport.hevc_support.d3d12_caps.MinLumaTransformUnitSize);
1023                uint8_t maxTuSize = d3d12_video_encoder_convert_12tusize_to_pixel_size_hevc(codecSupport.hevc_support.d3d12_caps.MaxLumaTransformUnitSize);
1024 
1025                codecSupport.hevc_support.hevc_block_sizes.bits.log2_max_coding_tree_block_size_minus3
1026                               = static_cast<uint8_t>(CtbLog2SizeY - 3);
1027                codecSupport.hevc_support.hevc_block_sizes.bits.log2_min_coding_tree_block_size_minus3
1028                               = static_cast<uint8_t>(CtbLog2SizeY - 3);
1029 
1030                codecSupport.hevc_support.hevc_block_sizes.bits.log2_min_luma_coding_block_size_minus3
1031                               = static_cast<uint8_t>(MinCbLog2SizeY - 3);
1032 
1033                codecSupport.hevc_support.hevc_block_sizes.bits.log2_max_luma_transform_block_size_minus2
1034                               = static_cast<uint8_t>(std::log2(maxTuSize) - 2);
1035 
1036                codecSupport.hevc_support.hevc_block_sizes.bits.log2_min_luma_transform_block_size_minus2
1037                               = static_cast<uint8_t>(std::log2(minTuSize) - 2);
1038 
1039                codecSupport.hevc_support.hevc_block_sizes.bits.max_max_transform_hierarchy_depth_inter
1040                               = codecSupport.hevc_support.d3d12_caps.max_transform_hierarchy_depth_inter;
1041 
1042                codecSupport.hevc_support.hevc_block_sizes.bits.min_max_transform_hierarchy_depth_inter
1043                               = codecSupport.hevc_support.d3d12_caps.max_transform_hierarchy_depth_inter;
1044 
1045                codecSupport.hevc_support.hevc_block_sizes.bits.max_max_transform_hierarchy_depth_intra
1046                               = codecSupport.hevc_support.d3d12_caps.max_transform_hierarchy_depth_intra;
1047 
1048                codecSupport.hevc_support.hevc_block_sizes.bits.min_max_transform_hierarchy_depth_intra
1049                               = codecSupport.hevc_support.d3d12_caps.max_transform_hierarchy_depth_intra;
1050 
1051                codecSupport.hevc_support.hevc_block_sizes.bits.log2_max_pcm_coding_block_size_minus3 = 0; // No PCM Supported
1052                codecSupport.hevc_support.hevc_block_sizes.bits.log2_min_pcm_coding_block_size_minus3 = 0; // No PCM Supported
1053 
1054                // HEVC range ext caps
1055                codecSupport.hevc_support.hevc_range_ext.value = 0;
1056                codecSupport.hevc_support.hevc_range_ext.bits.supported_diff_cu_chroma_qp_offset_depth_values = codecSupport.hevc_support.d3d12_caps.allowed_diff_cu_chroma_qp_offset_depth_values;
1057                codecSupport.hevc_support.hevc_range_ext.bits.supported_log2_sao_offset_scale_luma_values = codecSupport.hevc_support.d3d12_caps.allowed_log2_sao_offset_scale_luma_values;
1058                codecSupport.hevc_support.hevc_range_ext.bits.supported_log2_sao_offset_scale_chroma_values = codecSupport.hevc_support.d3d12_caps.allowed_log2_sao_offset_scale_chroma_values;
1059                codecSupport.hevc_support.hevc_range_ext.bits.supported_log2_max_transform_skip_block_size_minus2_values = codecSupport.hevc_support.d3d12_caps.allowed_log2_max_transform_skip_block_size_minus2_values;
1060                codecSupport.hevc_support.hevc_range_ext.bits.min_chroma_qp_offset_list_len_minus1_values = 0;
1061                codecSupport.hevc_support.hevc_range_ext.bits.max_chroma_qp_offset_list_len_minus1_values = 0;
1062                if (codecSupport.hevc_support.d3d12_caps.allowed_chroma_qp_offset_list_len_minus1_values)
1063                {
1064                   codecSupport.hevc_support.hevc_range_ext.bits.min_chroma_qp_offset_list_len_minus1_values = 5;
1065                   codecSupport.hevc_support.hevc_range_ext.bits.max_chroma_qp_offset_list_len_minus1_values = 0;
1066                   for (uint32_t i = 0; i < 6 /*Codec valid range for support for chroma_qp_offset_list_len_minus1 is [0, 5]*/; i++)
1067                   {
1068                      if ((codecSupport.hevc_support.d3d12_caps.allowed_chroma_qp_offset_list_len_minus1_values & (1 << i)) != 0)
1069                      {
1070                         codecSupport.hevc_support.hevc_range_ext.bits.min_chroma_qp_offset_list_len_minus1_values = std::min(codecSupport.hevc_support.hevc_range_ext.bits.min_chroma_qp_offset_list_len_minus1_values, i);
1071                         codecSupport.hevc_support.hevc_range_ext.bits.max_chroma_qp_offset_list_len_minus1_values = std::max(codecSupport.hevc_support.hevc_range_ext.bits.max_chroma_qp_offset_list_len_minus1_values, i);
1072                      }
1073                   }
1074                }
1075 
1076                codecSupport.hevc_support.hevc_range_ext_flags.value = 0;
1077                if (codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_TRANSFORM_SKIP_ROTATION_ENABLED_SUPPORT)
1078                   codecSupport.hevc_support.hevc_range_ext_flags.bits.supports_transform_skip_rotation_enabled_flag |= PIPE_ENC_FEATURE_SUPPORTED;
1079 
1080                if (codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_TRANSFORM_SKIP_ROTATION_ENABLED_REQUIRED)
1081                   codecSupport.hevc_support.hevc_range_ext_flags.bits.supports_transform_skip_rotation_enabled_flag |= PIPE_ENC_FEATURE_REQUIRED;
1082 
1083                if (codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_TRANSFORM_SKIP_CONTEXT_ENABLED_SUPPORT)
1084                   codecSupport.hevc_support.hevc_range_ext_flags.bits.supports_transform_skip_context_enabled_flag |= PIPE_ENC_FEATURE_SUPPORTED;
1085 
1086                if (codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_TRANSFORM_SKIP_CONTEXT_ENABLED_REQUIRED)
1087                   codecSupport.hevc_support.hevc_range_ext_flags.bits.supports_transform_skip_context_enabled_flag |= PIPE_ENC_FEATURE_REQUIRED;
1088 
1089                if (codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_IMPLICIT_RDPCM_ENABLED_SUPPORT)
1090                   codecSupport.hevc_support.hevc_range_ext_flags.bits.supports_implicit_rdpcm_enabled_flag |= PIPE_ENC_FEATURE_SUPPORTED;
1091 
1092                if (codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_IMPLICIT_RDPCM_ENABLED_REQUIRED)
1093                   codecSupport.hevc_support.hevc_range_ext_flags.bits.supports_implicit_rdpcm_enabled_flag |= PIPE_ENC_FEATURE_REQUIRED;
1094 
1095                if (codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_EXPLICIT_RDPCM_ENABLED_SUPPORT)
1096                   codecSupport.hevc_support.hevc_range_ext_flags.bits.supports_explicit_rdpcm_enabled_flag |= PIPE_ENC_FEATURE_SUPPORTED;
1097 
1098                if (codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_EXPLICIT_RDPCM_ENABLED_REQUIRED)
1099                   codecSupport.hevc_support.hevc_range_ext_flags.bits.supports_explicit_rdpcm_enabled_flag |= PIPE_ENC_FEATURE_REQUIRED;
1100 
1101                if (codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_EXTENDED_PRECISION_PROCESSING_SUPPORT)
1102                   codecSupport.hevc_support.hevc_range_ext_flags.bits.supports_extended_precision_processing_flag |= PIPE_ENC_FEATURE_SUPPORTED;
1103 
1104                if (codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_EXTENDED_PRECISION_PROCESSING_REQUIRED)
1105                   codecSupport.hevc_support.hevc_range_ext_flags.bits.supports_extended_precision_processing_flag |= PIPE_ENC_FEATURE_REQUIRED;
1106 
1107                if (codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_INTRA_SMOOTHING_DISABLED_SUPPORT)
1108                   codecSupport.hevc_support.hevc_range_ext_flags.bits.supports_intra_smoothing_disabled_flag |= PIPE_ENC_FEATURE_SUPPORTED;
1109 
1110                if (codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_INTRA_SMOOTHING_DISABLED_REQUIRED)
1111                   codecSupport.hevc_support.hevc_range_ext_flags.bits.supports_intra_smoothing_disabled_flag |= PIPE_ENC_FEATURE_REQUIRED;
1112 
1113                if (codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_HIGH_PRECISION_OFFSETS_ENABLED_SUPPORT)
1114                   codecSupport.hevc_support.hevc_range_ext_flags.bits.supports_high_precision_offsets_enabled_flag |= PIPE_ENC_FEATURE_SUPPORTED;
1115 
1116                if (codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_HIGH_PRECISION_OFFSETS_ENABLED_REQUIRED)
1117                   codecSupport.hevc_support.hevc_range_ext_flags.bits.supports_high_precision_offsets_enabled_flag |= PIPE_ENC_FEATURE_REQUIRED;
1118 
1119                if (codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_PERSISTENT_RICE_ADAPTATION_ENABLED_SUPPORT)
1120                   codecSupport.hevc_support.hevc_range_ext_flags.bits.supports_persistent_rice_adaptation_enabled_flag |= PIPE_ENC_FEATURE_SUPPORTED;
1121 
1122                if (codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_PERSISTENT_RICE_ADAPTATION_ENABLED_REQUIRED)
1123                   codecSupport.hevc_support.hevc_range_ext_flags.bits.supports_persistent_rice_adaptation_enabled_flag |= PIPE_ENC_FEATURE_REQUIRED;
1124 
1125                if (codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_CABAC_BYPASS_ALIGNMENT_ENABLED_SUPPORT)
1126                   codecSupport.hevc_support.hevc_range_ext_flags.bits.supports_cabac_bypass_alignment_enabled_flag |= PIPE_ENC_FEATURE_SUPPORTED;
1127 
1128                if (codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_CABAC_BYPASS_ALIGNMENT_ENABLED_REQUIRED)
1129                   codecSupport.hevc_support.hevc_range_ext_flags.bits.supports_cabac_bypass_alignment_enabled_flag |= PIPE_ENC_FEATURE_REQUIRED;
1130 
1131                if (codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_CROSS_COMPONENT_PREDICTION_ENABLED_FLAG_SUPPORT)
1132                   codecSupport.hevc_support.hevc_range_ext_flags.bits.supports_cross_component_prediction_enabled_flag |= PIPE_ENC_FEATURE_SUPPORTED;
1133 
1134                if (codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_CROSS_COMPONENT_PREDICTION_ENABLED_FLAG_REQUIRED)
1135                   codecSupport.hevc_support.hevc_range_ext_flags.bits.supports_cross_component_prediction_enabled_flag |= PIPE_ENC_FEATURE_REQUIRED;
1136 
1137                if (codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_CHROMA_QP_OFFSET_LIST_ENABLED_FLAG_SUPPORT)
1138                   codecSupport.hevc_support.hevc_range_ext_flags.bits.supports_chroma_qp_offset_list_enabled_flag |= PIPE_ENC_FEATURE_SUPPORTED;
1139 
1140                if (codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_CHROMA_QP_OFFSET_LIST_ENABLED_FLAG_REQUIRED)
1141                   codecSupport.hevc_support.hevc_range_ext_flags.bits.supports_chroma_qp_offset_list_enabled_flag |= PIPE_ENC_FEATURE_REQUIRED;
1142 
1143                // Feature flags
1144 
1145                uint32_t ref_l0 = maxReferencesPerFrame       & 0xffff;
1146                uint32_t ref_l1 = maxReferencesPerFrame >> 16 & 0xffff;
1147 
1148                codecSupport.hevc_support.prediction_direction = PIPE_H265_PRED_DIRECTION_ALL;
1149                if(ref_l0)
1150                   codecSupport.hevc_support.prediction_direction |= PIPE_H265_PRED_DIRECTION_PREVIOUS;
1151                if(ref_l1)
1152                   codecSupport.hevc_support.prediction_direction |= PIPE_H265_PRED_DIRECTION_FUTURE;
1153 
1154                codecSupport.hevc_support.hevc_features.bits.separate_colour_planes = PIPE_ENC_FEATURE_NOT_SUPPORTED;
1155                if (codecSupport.hevc_support.d3d12_caps.SupportFlags1 & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG1_SEPARATE_COLOUR_PLANE_SUPPORT)
1156                   codecSupport.hevc_support.hevc_features.bits.separate_colour_planes = PIPE_ENC_FEATURE_SUPPORTED;
1157 
1158                if (codecSupport.hevc_support.d3d12_caps.SupportFlags1 & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG1_SEPARATE_COLOUR_PLANE_REQUIRED)
1159                   codecSupport.hevc_support.hevc_features.bits.separate_colour_planes = PIPE_ENC_FEATURE_REQUIRED;
1160                codecSupport.hevc_support.hevc_features.bits.scaling_lists = PIPE_ENC_FEATURE_NOT_SUPPORTED;
1161                codecSupport.hevc_support.hevc_features.bits.pcm = PIPE_ENC_FEATURE_NOT_SUPPORTED;
1162                codecSupport.hevc_support.hevc_features.bits.temporal_mvp = PIPE_ENC_FEATURE_NOT_SUPPORTED;
1163                codecSupport.hevc_support.hevc_features.bits.strong_intra_smoothing = PIPE_ENC_FEATURE_NOT_SUPPORTED;
1164                codecSupport.hevc_support.hevc_features.bits.dependent_slices = PIPE_ENC_FEATURE_NOT_SUPPORTED;
1165                codecSupport.hevc_support.hevc_features.bits.sign_data_hiding = PIPE_ENC_FEATURE_NOT_SUPPORTED;
1166                codecSupport.hevc_support.hevc_features.bits.weighted_prediction = PIPE_ENC_FEATURE_NOT_SUPPORTED;
1167                codecSupport.hevc_support.hevc_features.bits.transquant_bypass = PIPE_ENC_FEATURE_NOT_SUPPORTED;
1168                codecSupport.hevc_support.hevc_features.bits.deblocking_filter_disable = PIPE_ENC_FEATURE_NOT_SUPPORTED;
1169 
1170                /* cu_qp_delta always required to be 1 in https://github.com/microsoft/DirectX-Specs/blob/master/d3d/D3D12VideoEncoding.md */
1171                codecSupport.hevc_support.hevc_features.bits.cu_qp_delta = (PIPE_ENC_FEATURE_SUPPORTED | PIPE_ENC_FEATURE_REQUIRED);
1172 
1173                if ((codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_P_FRAMES_IMPLEMENTED_AS_LOW_DELAY_B_FRAMES) != 0)
1174                   codecSupport.hevc_support.prediction_direction |= PIPE_H265_PRED_DIRECTION_BI_NOT_EMPTY;
1175 
1176                if ((codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_ASYMETRIC_MOTION_PARTITION_SUPPORT) != 0)
1177                   codecSupport.hevc_support.hevc_features.bits.amp = PIPE_ENC_FEATURE_SUPPORTED;
1178 
1179                if ((codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_ASYMETRIC_MOTION_PARTITION_REQUIRED) != 0)
1180                   codecSupport.hevc_support.hevc_features.bits.amp = (PIPE_ENC_FEATURE_SUPPORTED | PIPE_ENC_FEATURE_REQUIRED);
1181 
1182                if ((codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_SAO_FILTER_SUPPORT) != 0)
1183                   codecSupport.hevc_support.hevc_features.bits.sao = PIPE_ENC_FEATURE_SUPPORTED;
1184 
1185                if ((codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_CONSTRAINED_INTRAPREDICTION_SUPPORT) != 0)
1186                   codecSupport.hevc_support.hevc_features.bits.constrained_intra_pred = PIPE_ENC_FEATURE_SUPPORTED;
1187                if ((codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_TRANSFORM_SKIP_SUPPORT) != 0)
1188                   codecSupport.hevc_support.hevc_features.bits.transform_skip = PIPE_ENC_FEATURE_SUPPORTED;
1189 
1190                DXGI_FORMAT encodeFormat = d3d12_convert_pipe_video_profile_to_dxgi_format(profile);
1191                supportsProfile = supportsProfile &&
1192                                  d3d12_video_encode_supported_resolution_range(codecDesc, minRes, maxRes, alignRes, spD3D12VideoDevice.Get());
1193 
1194                D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT1 capEncoderSupportData1 = {};
1195                D3D12_FEATURE_DATA_VIDEO_ENCODER_RESOLUTION_SUPPORT_LIMITS resolutionDepCaps;
1196                capEncoderSupportData1.SubregionFrameEncoding = (supportedSliceStructures == PIPE_VIDEO_CAP_SLICE_STRUCTURE_NONE) ?
1197                                                                 D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_FULL_FRAME :
1198                                                                 D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_PARTITIONING_SUBREGIONS_PER_FRAME;
1199                D3D12_VIDEO_ENCODER_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_SLICES sliceData = { };
1200                capEncoderSupportData1.SubregionFrameEncodingData.DataSize = sizeof(sliceData);
1201                capEncoderSupportData1.SubregionFrameEncodingData.pSlicesPartition_HEVC = &sliceData;
1202                supportsProfile = supportsProfile && d3d12_video_encode_support_caps(codecDesc,
1203                                                                                     maxRes,
1204                                                                                     encodeFormat,
1205                                                                                     spD3D12VideoDevice.Get(),
1206                                                                                     d3d12_codec_support,
1207                                                                                     capEncoderSupportData1,
1208                                                                                     resolutionDepCaps,
1209                                                                                     maxQualityLevels);
1210                if (supportedSliceStructures == PIPE_VIDEO_CAP_SLICE_STRUCTURE_NONE)
1211                   maxSlices = 0;
1212                else
1213                   maxSlices = resolutionDepCaps.MaxSubregionsNumber;
1214 
1215                maxIRDuration = resolutionDepCaps.MaxIntraRefreshFrameDuration;
1216                isRCMaxFrameSizeSupported = ((capEncoderSupportData1.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_RATE_CONTROL_MAX_FRAME_SIZE_AVAILABLE) != 0) ? 1 : 0;
1217 
1218                memset(&roi_support, 0, sizeof(roi_support));
1219                roi_support.bits.roi_rc_qp_delta_support = ((capEncoderSupportData1.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_RATE_CONTROL_DELTA_QP_AVAILABLE) != 0) ? 1 : 0;
1220                roi_support.bits.num_roi_regions = roi_support.bits.roi_rc_qp_delta_support ? PIPE_ENC_ROI_REGION_NUM_MAX : 0;
1221             }
1222          }
1223       } break;
1224 #endif
1225 #if VIDEO_CODEC_AV1ENC
1226       case PIPE_VIDEO_PROFILE_AV1_MAIN:
1227       {
1228          D3D12_VIDEO_ENCODER_PROFILE_DESC profDesc = {};
1229          D3D12_VIDEO_ENCODER_AV1_PROFILE profAV1 =
1230             d3d12_video_encoder_convert_profile_to_d3d12_enc_profile_av1(profile);
1231          profDesc.DataSize = sizeof(profAV1);
1232          profDesc.pAV1Profile = &profAV1;
1233          D3D12_VIDEO_ENCODER_CODEC codecDesc = d3d12_video_encoder_convert_codec_to_d3d12_enc_codec(profile);
1234          D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS minLvlSettingAV1 = { };
1235          D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS maxLvlSettingAV1 = { };
1236          D3D12_VIDEO_ENCODER_LEVEL_SETTING minLvl = {};
1237          D3D12_VIDEO_ENCODER_LEVEL_SETTING maxLvl = {};
1238          minLvl.pAV1LevelSetting = &minLvlSettingAV1;
1239          minLvl.DataSize = sizeof(minLvlSettingAV1);
1240          maxLvl.pAV1LevelSetting = &maxLvlSettingAV1;
1241          maxLvl.DataSize = sizeof(maxLvlSettingAV1);
1242          if (d3d12_video_encode_max_supported_level_for_profile(codecDesc,
1243                                                                 profDesc,
1244                                                                 minLvl,
1245                                                                 maxLvl,
1246                                                                 spD3D12VideoDevice.Get())) {
1247             d3d12_video_encoder_convert_d3d12_to_spec_level_av1(maxLvlSettingAV1.Level, maxLvlSpec);
1248 
1249             D3D12_VIDEO_ENCODER_PROFILE_DESC d3d12_profile;
1250             d3d12_profile.pAV1Profile = &profAV1;
1251             d3d12_profile.DataSize = sizeof(profAV1);
1252 
1253             maxReferencesPerFrame =
1254                d3d12_video_encode_supported_references_per_frame_structures(codecDesc,
1255                                                                             d3d12_profile,
1256                                                                             spD3D12VideoDevice.Get(),
1257                                                                             codecSupport);
1258 
1259             supportsProfile = d3d12_video_encode_get_av1_codec_support(codecDesc,
1260                                                                         profDesc,
1261                                                                         spD3D12VideoDevice.Get(),
1262                                                                         codecSupport.av1_support.d3d12_caps);
1263             if (supportsProfile) {
1264                d3d12_codec_support.DataSize = sizeof(codecSupport.av1_support.d3d12_caps);
1265                d3d12_codec_support.pAV1Support = &codecSupport.av1_support.d3d12_caps;
1266 
1267                if ((codecSupport.av1_support.d3d12_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_128x128_SUPERBLOCK) != 0)
1268                   codecSupport.av1_support.features.bits.support_128x128_superblock = PIPE_ENC_FEATURE_SUPPORTED;
1269 
1270                if ((codecSupport.av1_support.d3d12_caps.RequiredFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_128x128_SUPERBLOCK) != 0)
1271                   codecSupport.av1_support.features.bits.support_128x128_superblock = (PIPE_ENC_FEATURE_SUPPORTED | PIPE_ENC_FEATURE_REQUIRED);
1272 
1273                if ((codecSupport.av1_support.d3d12_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_FILTER_INTRA) != 0)
1274                   codecSupport.av1_support.features.bits.support_filter_intra = PIPE_ENC_FEATURE_SUPPORTED;
1275 
1276                if ((codecSupport.av1_support.d3d12_caps.RequiredFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_FILTER_INTRA) != 0)
1277                   codecSupport.av1_support.features.bits.support_filter_intra = (PIPE_ENC_FEATURE_SUPPORTED | PIPE_ENC_FEATURE_REQUIRED);
1278 
1279                if ((codecSupport.av1_support.d3d12_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_INTRA_EDGE_FILTER) != 0)
1280                   codecSupport.av1_support.features.bits.support_intra_edge_filter = PIPE_ENC_FEATURE_SUPPORTED;
1281 
1282                if ((codecSupport.av1_support.d3d12_caps.RequiredFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_INTRA_EDGE_FILTER) != 0)
1283                   codecSupport.av1_support.features.bits.support_intra_edge_filter = (PIPE_ENC_FEATURE_SUPPORTED | PIPE_ENC_FEATURE_REQUIRED);
1284 
1285                if ((codecSupport.av1_support.d3d12_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_INTERINTRA_COMPOUND) != 0)
1286                   codecSupport.av1_support.features.bits.support_interintra_compound = PIPE_ENC_FEATURE_SUPPORTED;
1287 
1288                if ((codecSupport.av1_support.d3d12_caps.RequiredFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_INTERINTRA_COMPOUND) != 0)
1289                   codecSupport.av1_support.features.bits.support_interintra_compound = (PIPE_ENC_FEATURE_SUPPORTED | PIPE_ENC_FEATURE_REQUIRED);
1290 
1291                if ((codecSupport.av1_support.d3d12_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_MASKED_COMPOUND) != 0)
1292                   codecSupport.av1_support.features.bits.support_masked_compound = PIPE_ENC_FEATURE_SUPPORTED;
1293 
1294                if ((codecSupport.av1_support.d3d12_caps.RequiredFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_MASKED_COMPOUND) != 0)
1295                   codecSupport.av1_support.features.bits.support_masked_compound = (PIPE_ENC_FEATURE_SUPPORTED | PIPE_ENC_FEATURE_REQUIRED);
1296 
1297                if ((codecSupport.av1_support.d3d12_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_WARPED_MOTION) != 0)
1298                   codecSupport.av1_support.features.bits.support_warped_motion = PIPE_ENC_FEATURE_SUPPORTED;
1299 
1300                if ((codecSupport.av1_support.d3d12_caps.RequiredFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_WARPED_MOTION) != 0)
1301                   codecSupport.av1_support.features.bits.support_warped_motion = (PIPE_ENC_FEATURE_SUPPORTED | PIPE_ENC_FEATURE_REQUIRED);
1302 
1303                if ((codecSupport.av1_support.d3d12_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_PALETTE_ENCODING) != 0)
1304                   codecSupport.av1_support.features.bits.support_palette_mode = PIPE_ENC_FEATURE_SUPPORTED;
1305 
1306                if ((codecSupport.av1_support.d3d12_caps.RequiredFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_PALETTE_ENCODING) != 0)
1307                   codecSupport.av1_support.features.bits.support_palette_mode = (PIPE_ENC_FEATURE_SUPPORTED | PIPE_ENC_FEATURE_REQUIRED);
1308 
1309                if ((codecSupport.av1_support.d3d12_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_DUAL_FILTER) != 0)
1310                   codecSupport.av1_support.features.bits.support_dual_filter = PIPE_ENC_FEATURE_SUPPORTED;
1311 
1312                if ((codecSupport.av1_support.d3d12_caps.RequiredFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_DUAL_FILTER) != 0)
1313                   codecSupport.av1_support.features.bits.support_dual_filter = (PIPE_ENC_FEATURE_SUPPORTED | PIPE_ENC_FEATURE_REQUIRED);
1314 
1315                if ((codecSupport.av1_support.d3d12_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_JNT_COMP) != 0)
1316                   codecSupport.av1_support.features.bits.support_jnt_comp = PIPE_ENC_FEATURE_SUPPORTED;
1317 
1318                if ((codecSupport.av1_support.d3d12_caps.RequiredFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_JNT_COMP) != 0)
1319                   codecSupport.av1_support.features.bits.support_jnt_comp = (PIPE_ENC_FEATURE_SUPPORTED | PIPE_ENC_FEATURE_REQUIRED);
1320 
1321                if ((codecSupport.av1_support.d3d12_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_FRAME_REFERENCE_MOTION_VECTORS) != 0)
1322                   codecSupport.av1_support.features.bits.support_ref_frame_mvs = PIPE_ENC_FEATURE_SUPPORTED;
1323 
1324                if ((codecSupport.av1_support.d3d12_caps.RequiredFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_FRAME_REFERENCE_MOTION_VECTORS) != 0)
1325                   codecSupport.av1_support.features.bits.support_ref_frame_mvs = (PIPE_ENC_FEATURE_SUPPORTED | PIPE_ENC_FEATURE_REQUIRED);
1326 
1327                if ((codecSupport.av1_support.d3d12_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_SUPER_RESOLUTION) != 0)
1328                   codecSupport.av1_support.features.bits.support_superres = PIPE_ENC_FEATURE_SUPPORTED;
1329 
1330                if ((codecSupport.av1_support.d3d12_caps.RequiredFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_SUPER_RESOLUTION) != 0)
1331                   codecSupport.av1_support.features.bits.support_superres = (PIPE_ENC_FEATURE_SUPPORTED | PIPE_ENC_FEATURE_REQUIRED);
1332 
1333                if ((codecSupport.av1_support.d3d12_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_LOOP_RESTORATION_FILTER) != 0)
1334                   codecSupport.av1_support.features.bits.support_restoration = PIPE_ENC_FEATURE_SUPPORTED;
1335 
1336                if ((codecSupport.av1_support.d3d12_caps.RequiredFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_LOOP_RESTORATION_FILTER) != 0)
1337                   codecSupport.av1_support.features.bits.support_restoration = (PIPE_ENC_FEATURE_SUPPORTED | PIPE_ENC_FEATURE_REQUIRED);
1338 
1339                if ((codecSupport.av1_support.d3d12_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_INTRA_BLOCK_COPY) != 0)
1340                   codecSupport.av1_support.features.bits.support_allow_intrabc = PIPE_ENC_FEATURE_SUPPORTED;
1341 
1342                if ((codecSupport.av1_support.d3d12_caps.RequiredFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_INTRA_BLOCK_COPY) != 0)
1343                   codecSupport.av1_support.features.bits.support_allow_intrabc = (PIPE_ENC_FEATURE_SUPPORTED | PIPE_ENC_FEATURE_REQUIRED);
1344 
1345                if ((codecSupport.av1_support.d3d12_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_CDEF_FILTERING) != 0)
1346                   codecSupport.av1_support.features.bits.support_cdef_channel_strength = PIPE_ENC_FEATURE_SUPPORTED;
1347 
1348                if ((codecSupport.av1_support.d3d12_caps.RequiredFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_CDEF_FILTERING) != 0)
1349                   codecSupport.av1_support.features.bits.support_cdef_channel_strength = (PIPE_ENC_FEATURE_SUPPORTED | PIPE_ENC_FEATURE_REQUIRED);
1350 
1351                // pipe_av1_enc_cap_features_ext1
1352                if ((codecSupport.av1_support.d3d12_caps.SupportedInterpolationFilters & D3D12_VIDEO_ENCODER_AV1_INTERPOLATION_FILTERS_FLAG_EIGHTTAP) != 0)
1353                   codecSupport.av1_support.features_ext1.bits.interpolation_filter |= PIPE_VIDEO_CAP_ENC_AV1_INTERPOLATION_FILTER_EIGHT_TAP;
1354 
1355                if ((codecSupport.av1_support.d3d12_caps.SupportedInterpolationFilters & D3D12_VIDEO_ENCODER_AV1_INTERPOLATION_FILTERS_FLAG_EIGHTTAP_SMOOTH) != 0)
1356                   codecSupport.av1_support.features_ext1.bits.interpolation_filter |= PIPE_VIDEO_CAP_ENC_AV1_INTERPOLATION_FILTER_EIGHT_TAP_SMOOTH;
1357 
1358                if ((codecSupport.av1_support.d3d12_caps.SupportedInterpolationFilters & D3D12_VIDEO_ENCODER_AV1_INTERPOLATION_FILTERS_FLAG_EIGHTTAP_SHARP) != 0)
1359                   codecSupport.av1_support.features_ext1.bits.interpolation_filter |= PIPE_VIDEO_CAP_ENC_AV1_INTERPOLATION_FILTER_EIGHT_TAP_SHARP;
1360 
1361                if ((codecSupport.av1_support.d3d12_caps.SupportedInterpolationFilters & D3D12_VIDEO_ENCODER_AV1_INTERPOLATION_FILTERS_FLAG_BILINEAR) != 0)
1362                   codecSupport.av1_support.features_ext1.bits.interpolation_filter |= PIPE_VIDEO_CAP_ENC_AV1_INTERPOLATION_FILTER_BILINEAR;
1363 
1364                if ((codecSupport.av1_support.d3d12_caps.SupportedInterpolationFilters & D3D12_VIDEO_ENCODER_AV1_INTERPOLATION_FILTERS_FLAG_SWITCHABLE) != 0)
1365                   codecSupport.av1_support.features_ext1.bits.interpolation_filter |= PIPE_VIDEO_CAP_ENC_AV1_INTERPOLATION_FILTER_SWITCHABLE;
1366 
1367                if ((codecSupport.av1_support.d3d12_caps.SupportedSegmentationModes & D3D12_VIDEO_ENCODER_AV1_SEGMENTATION_MODE_FLAG_DISABLED) != 0)
1368                   codecSupport.av1_support.features_ext1.bits.segment_feature_support = 0;
1369 
1370                if ((codecSupport.av1_support.d3d12_caps.SupportedSegmentationModes & D3D12_VIDEO_ENCODER_AV1_SEGMENTATION_MODE_FLAG_ALT_Q) != 0)
1371                   codecSupport.av1_support.features_ext1.bits.segment_feature_support |= 0x1;
1372 
1373                if ((codecSupport.av1_support.d3d12_caps.SupportedSegmentationModes & D3D12_VIDEO_ENCODER_AV1_SEGMENTATION_MODE_FLAG_ALT_LF_Y_V) != 0)
1374                   codecSupport.av1_support.features_ext1.bits.segment_feature_support |= 0x2;
1375 
1376                if ((codecSupport.av1_support.d3d12_caps.SupportedSegmentationModes & D3D12_VIDEO_ENCODER_AV1_SEGMENTATION_MODE_FLAG_ALT_LF_Y_H) != 0)
1377                   codecSupport.av1_support.features_ext1.bits.segment_feature_support |= 0x4;
1378 
1379                if ((codecSupport.av1_support.d3d12_caps.SupportedSegmentationModes & D3D12_VIDEO_ENCODER_AV1_SEGMENTATION_MODE_FLAG_ALT_LF_U) != 0)
1380                   codecSupport.av1_support.features_ext1.bits.segment_feature_support |= 0x8;
1381 
1382                if ((codecSupport.av1_support.d3d12_caps.SupportedSegmentationModes & D3D12_VIDEO_ENCODER_AV1_SEGMENTATION_MODE_FLAG_ALT_LF_V) != 0)
1383                   codecSupport.av1_support.features_ext1.bits.segment_feature_support |= 0x10;
1384 
1385                if ((codecSupport.av1_support.d3d12_caps.SupportedSegmentationModes & D3D12_VIDEO_ENCODER_AV1_SEGMENTATION_MODE_FLAG_REF_FRAME) != 0)
1386                   codecSupport.av1_support.features_ext1.bits.segment_feature_support |= 0x20;
1387 
1388                if ((codecSupport.av1_support.d3d12_caps.SupportedSegmentationModes & D3D12_VIDEO_ENCODER_AV1_SEGMENTATION_MODE_FLAG_ALT_SKIP) != 0)
1389                   codecSupport.av1_support.features_ext1.bits.segment_feature_support |= 0x40;
1390 
1391                if ((codecSupport.av1_support.d3d12_caps.SupportedSegmentationModes & D3D12_VIDEO_ENCODER_AV1_SEGMENTATION_MODE_FLAG_ALT_GLOBALMV) != 0)
1392                   codecSupport.av1_support.features_ext1.bits.segment_feature_support |= 0x80;
1393 
1394                // pipe_av1_enc_cap_features_ext2
1395                codecSupport.av1_support.features_ext2.bits.obu_size_bytes_minus1 = 4 - 1; // Default 4 bytes (reported minus 1)
1396 
1397                // tx_mode_support query cap
1398                {
1399                   // libva tx_mode_support, PIPE_XX and D3D12 flags are defined with the same numerical values.
1400                   static_assert(static_cast<uint32_t>(D3D12_VIDEO_ENCODER_AV1_TX_MODE_FLAG_SELECT) ==
1401                      static_cast<uint32_t>(PIPE_VIDEO_CAP_ENC_AV1_TX_MODE_SELECT));
1402                   static_assert(static_cast<uint32_t>(D3D12_VIDEO_ENCODER_AV1_TX_MODE_FLAG_LARGEST) ==
1403                      static_cast<uint32_t>(PIPE_VIDEO_CAP_ENC_AV1_TX_MODE_LARGEST));
1404                   static_assert(static_cast<uint32_t>(D3D12_VIDEO_ENCODER_AV1_TX_MODE_FLAG_ONLY4x4) ==
1405                      static_cast<uint32_t>(PIPE_VIDEO_CAP_ENC_AV1_TX_MODE_ONLY_4X4));
1406 
1407                   // Iterate over the tx_modes and generate the D3D12_VIDEO_ENCODER_AV1_TX_MODE_FLAGS d3d12SupportFlag
1408                   for(uint8_t i = D3D12_VIDEO_ENCODER_AV1_TX_MODE_ONLY4x4; i <= D3D12_VIDEO_ENCODER_AV1_TX_MODE_SELECT; i++)
1409                   {
1410                      uint32_t d3d12SupportFlag = (1 << i); // See definition of D3D12_VIDEO_ENCODER_AV1_TX_MODE_FLAGS
1411                      // Check the current d3d12SupportFlag (ie. D3D12_VIDEO_ENCODER_AV1_TX_MODE_FLAG_XXX) is supported for all frame types
1412                      bool tx_mode_supported = true;
1413                      for(uint8_t j = D3D12_VIDEO_ENCODER_AV1_FRAME_TYPE_KEY_FRAME; j <= D3D12_VIDEO_ENCODER_AV1_FRAME_TYPE_SWITCH_FRAME; j++)
1414                      {
1415                         // Check frame supported by picture control caps, otherwise don't check against this frame type
1416                         if(codecSupport.av1_support.d3d12_picture_control.SupportedFrameTypes & (1 << j /* See D3D12_VIDEO_ENCODER_AV1_FRAME_TYPE_FLAGS */))
1417                            tx_mode_supported &= ((codecSupport.av1_support.d3d12_caps.SupportedTxModes[j] & d3d12SupportFlag) != 0);
1418                      }
1419 
1420                      // When supported for all frames, report it as part of the bitmask
1421                      if (tx_mode_supported)
1422                         codecSupport.av1_support.features_ext2.bits.tx_mode_support |= d3d12SupportFlag;
1423                   }
1424 
1425                   // As per d3d12 spec, driver must support at least one default mode for all frame types
1426                   // Workaround for mismatch between VAAPI/D3D12 and TxMode support for all/some frame types
1427                   if (!codecSupport.av1_support.features_ext2.bits.tx_mode_support)
1428                   {
1429                      debug_printf("[d3d12_has_video_encode_support] Reporting features_ext2.bits.tx_mode_support = D3D12_VIDEO_ENCODER_AV1_TX_MODE_FLAG_SELECT"
1430                      " due to mismatch between D3D12/VAAPI TxMode support semantic");
1431                      codecSupport.av1_support.features_ext2.bits.tx_mode_support = D3D12_VIDEO_ENCODER_AV1_TX_MODE_FLAG_SELECT;
1432                   }
1433                }
1434 
1435                supportsProfile = supportsProfile &&
1436                                  d3d12_video_encode_supported_resolution_range(codecDesc, minRes, maxRes, alignRes, spD3D12VideoDevice.Get());
1437 
1438                D3D12_VIDEO_ENCODER_AV1_FRAME_SUBREGION_LAYOUT_CONFIG_SUPPORT av1TileSupport = {};
1439                d3d12_video_encode_supported_tile_structures(codecDesc,
1440                                                             profDesc,
1441                                                             maxLvl,
1442                                                             spD3D12VideoDevice.Get(),
1443                                                             maxRes,
1444                                                             supportedSliceStructures,
1445                                                             av1TileSupport // out
1446                                                          );
1447                // Cannot pass pipe 2 bit-field as reference, use aux variable instead.
1448                codecSupport.av1_support.features_ext2.bits.tile_size_bytes_minus1 = av1TileSupport.TileSizeBytesMinus1;
1449                max_tile_rows = av1TileSupport.MaxTileRows;
1450                max_tile_cols = av1TileSupport.MaxTileCols;
1451 
1452                DXGI_FORMAT encodeFormat = d3d12_convert_pipe_video_profile_to_dxgi_format(profile);
1453 
1454                D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT1 capEncoderSupportData1 = {};
1455                D3D12_FEATURE_DATA_VIDEO_ENCODER_RESOLUTION_SUPPORT_LIMITS resolutionDepCaps;
1456                capEncoderSupportData1.SubregionFrameEncoding = (supportedSliceStructures == PIPE_VIDEO_CAP_SLICE_STRUCTURE_NONE) ?
1457                                                                 D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_FULL_FRAME :
1458                                                                 D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_GRID_PARTITION;
1459 
1460                capEncoderSupportData1.SubregionFrameEncodingData.DataSize = sizeof(av1TileSupport.TilesConfiguration);
1461                capEncoderSupportData1.SubregionFrameEncodingData.pTilesPartition_AV1 = &av1TileSupport.TilesConfiguration;
1462 
1463                supportsProfile = supportsProfile && d3d12_video_encode_support_caps(codecDesc,
1464                                                                                     maxRes,
1465                                                                                     encodeFormat,
1466                                                                                     spD3D12VideoDevice.Get(),
1467                                                                                     d3d12_codec_support,
1468                                                                                     capEncoderSupportData1,
1469                                                                                     resolutionDepCaps,
1470                                                                                     maxQualityLevels);
1471                if (supportedSliceStructures == PIPE_VIDEO_CAP_SLICE_STRUCTURE_NONE)
1472                   maxSlices = 0;
1473                else
1474                   maxSlices = resolutionDepCaps.MaxSubregionsNumber;
1475 
1476                maxIRDuration = resolutionDepCaps.MaxIntraRefreshFrameDuration;
1477                codecSupport.av1_support.features_ext2.bits.max_tile_num_minus1 = maxSlices - 1;
1478 
1479                isRCMaxFrameSizeSupported = ((capEncoderSupportData1.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_RATE_CONTROL_MAX_FRAME_SIZE_AVAILABLE) != 0) ? 1 : 0;
1480                memset(&roi_support, 0, sizeof(roi_support));
1481                roi_support.bits.roi_rc_qp_delta_support = ((capEncoderSupportData1.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_RATE_CONTROL_DELTA_QP_AVAILABLE) != 0) ? 1 : 0;
1482                roi_support.bits.num_roi_regions = roi_support.bits.roi_rc_qp_delta_support ? PIPE_ENC_ROI_REGION_NUM_MAX : 0;
1483             }
1484          }
1485       } break;
1486 #endif // #if VIDEO_CODEC_AV1ENC
1487       default:
1488          supportsProfile = false;
1489    }
1490 
1491    return VideoFeatureAreaSupport.VideoEncodeSupport && supportsProfile;
1492 }
1493 
1494 static int
d3d12_screen_get_video_param_decode(struct pipe_screen * pscreen,enum pipe_video_profile profile,enum pipe_video_entrypoint entrypoint,enum pipe_video_cap param)1495 d3d12_screen_get_video_param_decode(struct pipe_screen *pscreen,
1496                                     enum pipe_video_profile profile,
1497                                     enum pipe_video_entrypoint entrypoint,
1498                                     enum pipe_video_cap param)
1499 {
1500    switch (param) {
1501       case PIPE_VIDEO_CAP_REQUIRES_FLUSH_ON_END_FRAME:
1502          /* As sometimes we need to copy the output
1503             and sync with the context, we handle the
1504             flush internally on end frame for decode
1505          */
1506          return 0;
1507       case PIPE_VIDEO_CAP_NPOT_TEXTURES:
1508          return 1;
1509       case PIPE_VIDEO_CAP_MAX_WIDTH:
1510       case PIPE_VIDEO_CAP_MAX_HEIGHT:
1511       case PIPE_VIDEO_CAP_MAX_LEVEL:
1512       case PIPE_VIDEO_CAP_MIN_WIDTH:
1513       case PIPE_VIDEO_CAP_MIN_HEIGHT:
1514       case PIPE_VIDEO_CAP_SUPPORTED:
1515       {
1516          if (d3d12_has_video_decode_support(pscreen, profile)) {
1517             DXGI_FORMAT format = d3d12_convert_pipe_video_profile_to_dxgi_format(profile);
1518             auto pipeFmt = d3d12_get_pipe_format(format);
1519             bool formatSupported = pscreen->is_video_format_supported(pscreen, pipeFmt, profile, entrypoint);
1520             if (formatSupported) {
1521                GUID decodeGUID = d3d12_video_decoder_convert_pipe_video_profile_to_d3d12_profile(profile);
1522                GUID emptyGUID = {};
1523                if (decodeGUID != emptyGUID) {
1524                   bool supportAny = false;
1525                   D3D12_FEATURE_DATA_VIDEO_DECODE_SUPPORT outSupportedConfig = {};
1526                   D3D12_VIDEO_DECODE_CONFIGURATION decoderConfig = { decodeGUID,
1527                                                                      D3D12_BITSTREAM_ENCRYPTION_TYPE_NONE,
1528                                                                      D3D12_VIDEO_FRAME_CODED_INTERLACE_TYPE_NONE };
1529 
1530                   d3d12_video_resolution_to_level_mapping_entry lowestSupportedConfig = {};
1531                   d3d12_video_resolution_to_level_mapping_entry bestSupportedConfig = {};
1532                      get_level_resolution_video_decode_support(decoderConfig,
1533                                                                    format,
1534                                                                    pscreen,
1535                                                                    supportAny,
1536                                                                    outSupportedConfig,
1537                                                                    bestSupportedConfig,
1538                                                                    lowestSupportedConfig);
1539                   if (supportAny) {
1540                      if (param == PIPE_VIDEO_CAP_MAX_WIDTH) {
1541                         return bestSupportedConfig.resolution.Width;
1542                      } else if (param == PIPE_VIDEO_CAP_MAX_HEIGHT) {
1543                         return bestSupportedConfig.resolution.Height;
1544                      } else if (param == PIPE_VIDEO_CAP_MIN_WIDTH) {
1545                         return lowestSupportedConfig.resolution.Width;
1546                      } else if (param == PIPE_VIDEO_CAP_MIN_HEIGHT) {
1547                         return lowestSupportedConfig.resolution.Height;
1548                      } else if (param == PIPE_VIDEO_CAP_MAX_LEVEL) {
1549                         return bestSupportedConfig.level;
1550                      } else if (param == PIPE_VIDEO_CAP_SUPPORTED) {
1551                         return 1;
1552                      }
1553                   }
1554                }
1555             }
1556          }
1557          return 0;
1558       } break;
1559       case PIPE_VIDEO_CAP_PREFERED_FORMAT:
1560          return (profile == PIPE_VIDEO_PROFILE_UNKNOWN) ? PIPE_FORMAT_NV12 : d3d12_get_pipe_format(d3d12_convert_pipe_video_profile_to_dxgi_format(profile));
1561       case PIPE_VIDEO_CAP_PREFERS_INTERLACED:
1562          return false;
1563       case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED:
1564          return true;
1565       case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE:
1566          return true;
1567       case PIPE_VIDEO_CAP_SUPPORTS_CONTIGUOUS_PLANES_MAP:
1568          return true;
1569       default:
1570          debug_printf("[d3d12_screen_get_video_param] unknown video param: %d\n", param);
1571          return 0;
1572    }
1573 }
1574 
1575 
1576 static bool
d3d12_has_video_process_support(struct pipe_screen * pscreen,D3D12_FEATURE_DATA_VIDEO_PROCESS_SUPPORT & supportCaps,D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC & outMinSupportedInput,D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC & outMaxSupportedInput)1577 d3d12_has_video_process_support(struct pipe_screen *pscreen,
1578                                 D3D12_FEATURE_DATA_VIDEO_PROCESS_SUPPORT &supportCaps,
1579                                 D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC& outMinSupportedInput,
1580                                 D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC& outMaxSupportedInput)
1581 {
1582    ComPtr<ID3D12VideoDevice> spD3D12VideoDevice;
1583    struct d3d12_screen *pD3D12Screen = (struct d3d12_screen *) pscreen;
1584    if (FAILED(pD3D12Screen->dev->QueryInterface(IID_PPV_ARGS(spD3D12VideoDevice.GetAddressOf())))) {
1585       // No video process support in underlying d3d12 device (needs ID3D12VideoDevice)
1586       return false;
1587    }
1588 
1589    D3D12_FEATURE_DATA_VIDEO_FEATURE_AREA_SUPPORT VideoFeatureAreaSupport = {};
1590    if (FAILED(spD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_FEATURE_AREA_SUPPORT,
1591                                                       &VideoFeatureAreaSupport,
1592                                                       sizeof(VideoFeatureAreaSupport)))) {
1593       return false;
1594    }
1595 
1596    D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC resolutionsList[] = {
1597       { 8192, 8192 },   // 8k
1598       { 8192, 4320 },   // 8k - alternative
1599       { 7680, 4800 },   // 8k - alternative
1600       { 7680, 4320 },   // 8k - alternative
1601       { 4096, 2304 },   // 2160p (4K)
1602       { 4096, 2160 },   // 2160p (4K) - alternative
1603       { 2560, 1440 },   // 1440p
1604       { 1920, 1200 },   // 1200p
1605       { 1920, 1080 },   // 1080p
1606       { 1280, 720 },    // 720p
1607       { 800, 600 },
1608       { 352, 480 },
1609       { 352, 240 },
1610       { 176, 144 },
1611       { 128, 128 },
1612       { 96, 96 },
1613       { 64, 64 },
1614       { 32, 32 },
1615       { 16, 16 },
1616       { 8, 8 },
1617       { 4, 4 },
1618       { 2, 2 },
1619       { 1, 1 },
1620    };
1621 
1622    outMinSupportedInput = {};
1623    outMaxSupportedInput = {};
1624    uint32_t idxResol = 0;
1625    bool bSupportsAny = false;
1626    while (idxResol < ARRAY_SIZE(resolutionsList)) {
1627       supportCaps.InputSample.Width = resolutionsList[idxResol].Width;
1628       supportCaps.InputSample.Height = resolutionsList[idxResol].Height;
1629       if (SUCCEEDED(spD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_PROCESS_SUPPORT, &supportCaps, sizeof(supportCaps)))) {
1630          if ((supportCaps.SupportFlags & D3D12_VIDEO_PROCESS_SUPPORT_FLAG_SUPPORTED) != 0)
1631          {
1632             // Save the first (maximum)
1633             if(!bSupportsAny) {
1634                outMaxSupportedInput = resolutionsList[idxResol];
1635                bSupportsAny = true;
1636             }
1637 
1638             // Keep saving the other supported values to get the minimum
1639             outMinSupportedInput = resolutionsList[idxResol];
1640          }
1641       }
1642       idxResol++;
1643    }
1644 
1645    return VideoFeatureAreaSupport.VideoProcessSupport && bSupportsAny;
1646 }
1647 
1648 static int
d3d12_screen_get_video_param_postproc(struct pipe_screen * pscreen,enum pipe_video_profile profile,enum pipe_video_entrypoint entrypoint,enum pipe_video_cap param)1649 d3d12_screen_get_video_param_postproc(struct pipe_screen *pscreen,
1650                                     enum pipe_video_profile profile,
1651                                     enum pipe_video_entrypoint entrypoint,
1652                                     enum pipe_video_cap param)
1653 {
1654    switch (param) {
1655       case PIPE_VIDEO_CAP_REQUIRES_FLUSH_ON_END_FRAME:
1656          return 1;
1657       case PIPE_VIDEO_CAP_NPOT_TEXTURES:
1658          return 1;
1659       case PIPE_VIDEO_CAP_MAX_WIDTH:
1660       case PIPE_VIDEO_CAP_MAX_HEIGHT:
1661       case PIPE_VIDEO_CAP_MIN_WIDTH:
1662       case PIPE_VIDEO_CAP_MIN_HEIGHT:
1663       case PIPE_VIDEO_CAP_SUPPORTED:
1664       case PIPE_VIDEO_CAP_PREFERED_FORMAT:
1665       case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED:
1666       case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE:
1667       case PIPE_VIDEO_CAP_SUPPORTS_CONTIGUOUS_PLANES_MAP:
1668       case PIPE_VIDEO_CAP_VPP_MAX_INPUT_WIDTH:
1669       case PIPE_VIDEO_CAP_VPP_MAX_INPUT_HEIGHT:
1670       case PIPE_VIDEO_CAP_VPP_MIN_INPUT_WIDTH:
1671       case PIPE_VIDEO_CAP_VPP_MIN_INPUT_HEIGHT:
1672       case PIPE_VIDEO_CAP_VPP_MAX_OUTPUT_WIDTH:
1673       case PIPE_VIDEO_CAP_VPP_MAX_OUTPUT_HEIGHT:
1674       case PIPE_VIDEO_CAP_VPP_MIN_OUTPUT_WIDTH:
1675       case PIPE_VIDEO_CAP_VPP_MIN_OUTPUT_HEIGHT:
1676       case PIPE_VIDEO_CAP_VPP_ORIENTATION_MODES:
1677       case PIPE_VIDEO_CAP_VPP_BLEND_MODES:
1678       {
1679          // Assume defaults for now, we don't have the input args passed by get_video_param to be accurate here.
1680          const D3D12_VIDEO_FIELD_TYPE FieldType = D3D12_VIDEO_FIELD_TYPE_NONE;
1681          const D3D12_VIDEO_FRAME_STEREO_FORMAT StereoFormat = D3D12_VIDEO_FRAME_STEREO_FORMAT_NONE;
1682          const DXGI_RATIONAL FrameRate = { 30, 1 };
1683          const DXGI_FORMAT InputFormat = DXGI_FORMAT_NV12;
1684          const DXGI_COLOR_SPACE_TYPE InputColorSpace = DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709;
1685          const DXGI_FORMAT OutputFormat = DXGI_FORMAT_NV12;
1686          const DXGI_COLOR_SPACE_TYPE OutputColorSpace = DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709;
1687          const UINT Width = 1280;
1688          const UINT Height = 720;
1689          D3D12_FEATURE_DATA_VIDEO_PROCESS_SUPPORT supportCaps =
1690          {
1691             0, // NodeIndex
1692             { Width, Height, { InputFormat, InputColorSpace } },
1693             FieldType,
1694             StereoFormat,
1695             FrameRate,
1696             { OutputFormat, OutputColorSpace },
1697             StereoFormat,
1698             FrameRate,
1699          };
1700 
1701          D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC minSupportedInput = {};
1702          D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC maxSupportedInput = {};
1703          if (d3d12_has_video_process_support(pscreen, supportCaps, minSupportedInput, maxSupportedInput)) {
1704             if (param == PIPE_VIDEO_CAP_SUPPORTED) {
1705                return true;
1706             } else if (param == PIPE_VIDEO_CAP_PREFERED_FORMAT) {
1707                return  PIPE_FORMAT_NV12;
1708             } else if (param == PIPE_VIDEO_CAP_SUPPORTS_INTERLACED) {
1709                return false;
1710             } else if (param == PIPE_VIDEO_CAP_MIN_WIDTH) {
1711                return minSupportedInput.Width;
1712             } else if (param == PIPE_VIDEO_CAP_MIN_HEIGHT) {
1713                return minSupportedInput.Height;
1714             } else if (param == PIPE_VIDEO_CAP_MAX_WIDTH) {
1715                return maxSupportedInput.Width;
1716             } else if (param == PIPE_VIDEO_CAP_MAX_HEIGHT) {
1717                return maxSupportedInput.Height;
1718             } else if (param == PIPE_VIDEO_CAP_SUPPORTS_CONTIGUOUS_PLANES_MAP) {
1719                return true;
1720             } else if (param == PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE) {
1721                return true;
1722             } else if (param == PIPE_VIDEO_CAP_VPP_MAX_INPUT_WIDTH) {
1723                return supportCaps.ScaleSupport.OutputSizeRange.MaxWidth;
1724             } else if (param == PIPE_VIDEO_CAP_VPP_MAX_INPUT_HEIGHT) {
1725                return supportCaps.ScaleSupport.OutputSizeRange.MaxHeight;
1726             } else if (param == PIPE_VIDEO_CAP_VPP_MIN_INPUT_WIDTH) {
1727                return supportCaps.ScaleSupport.OutputSizeRange.MinWidth;
1728             } else if (param == PIPE_VIDEO_CAP_VPP_MIN_INPUT_HEIGHT) {
1729                return supportCaps.ScaleSupport.OutputSizeRange.MinHeight;
1730             } else if (param == PIPE_VIDEO_CAP_VPP_MAX_OUTPUT_WIDTH) {
1731                return supportCaps.ScaleSupport.OutputSizeRange.MaxWidth;
1732             } else if (param == PIPE_VIDEO_CAP_VPP_MAX_OUTPUT_HEIGHT) {
1733                return supportCaps.ScaleSupport.OutputSizeRange.MaxHeight;
1734             } else if (param == PIPE_VIDEO_CAP_VPP_MIN_OUTPUT_WIDTH) {
1735                return supportCaps.ScaleSupport.OutputSizeRange.MinWidth;
1736             } else if (param == PIPE_VIDEO_CAP_VPP_MIN_OUTPUT_HEIGHT) {
1737                return supportCaps.ScaleSupport.OutputSizeRange.MinHeight;
1738             } else if (param == PIPE_VIDEO_CAP_VPP_BLEND_MODES) {
1739                uint32_t blend_modes = PIPE_VIDEO_VPP_BLEND_MODE_NONE;
1740                if (((supportCaps.FeatureSupport & D3D12_VIDEO_PROCESS_FEATURE_FLAG_ALPHA_BLENDING) != 0)
1741                   && ((supportCaps.FeatureSupport & D3D12_VIDEO_PROCESS_FEATURE_FLAG_ALPHA_FILL) != 0))
1742                   {
1743                      blend_modes |= PIPE_VIDEO_VPP_BLEND_MODE_GLOBAL_ALPHA;
1744                   }
1745                   return blend_modes;
1746             } else if (param == PIPE_VIDEO_CAP_VPP_ORIENTATION_MODES) {
1747                 uint32_t orientation_modes = PIPE_VIDEO_VPP_ORIENTATION_DEFAULT;
1748                 if((supportCaps.FeatureSupport & D3D12_VIDEO_PROCESS_FEATURE_FLAG_FLIP) != 0) {
1749                   orientation_modes |= PIPE_VIDEO_VPP_FLIP_HORIZONTAL;
1750                   orientation_modes |= PIPE_VIDEO_VPP_FLIP_VERTICAL;
1751                 }
1752 
1753                 if((supportCaps.FeatureSupport & D3D12_VIDEO_PROCESS_FEATURE_FLAG_ROTATION) != 0) {
1754                   orientation_modes |= PIPE_VIDEO_VPP_ROTATION_90;
1755                   orientation_modes |= PIPE_VIDEO_VPP_ROTATION_180;
1756                   orientation_modes |= PIPE_VIDEO_VPP_ROTATION_270;
1757                 }
1758                 return orientation_modes;
1759             }
1760          }
1761          return 0;
1762       } break;
1763       default:
1764          return 0;
1765    }
1766 }
1767 
1768 static int
d3d12_screen_get_video_param_encode(struct pipe_screen * pscreen,enum pipe_video_profile profile,enum pipe_video_entrypoint entrypoint,enum pipe_video_cap param)1769 d3d12_screen_get_video_param_encode(struct pipe_screen *pscreen,
1770                                     enum pipe_video_profile profile,
1771                                     enum pipe_video_entrypoint entrypoint,
1772                                     enum pipe_video_cap param)
1773 {
1774    uint32_t maxLvlEncode = 0u;
1775    D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC minResEncode = {};
1776    D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC maxResEncode = {};
1777    union pipe_enc_cap_surface_alignment alignResEncode = {};
1778    uint32_t maxSlices = 0u;
1779    uint32_t supportedSliceStructures = 0u;
1780    uint32_t maxReferencesPerFrame = 0u;
1781    uint32_t isRCMaxFrameSizeSupported = 0u;
1782    uint32_t maxQualityLevels = 0u;
1783    uint32_t max_tile_rows = 0u;
1784    uint32_t max_tile_cols = 0u;
1785    uint32_t maxIRDuration = 0u;
1786    union pipe_enc_cap_roi roi_support = {};
1787    struct d3d12_encode_codec_support codec_specific_support;
1788    memset(&codec_specific_support, 0, sizeof(codec_specific_support));
1789    switch (param) {
1790       case PIPE_VIDEO_CAP_ENC_SUPPORTS_ASYNC_OPERATION:
1791          return D3D12_VIDEO_ENC_ASYNC;
1792       case PIPE_VIDEO_CAP_REQUIRES_FLUSH_ON_END_FRAME:
1793          return 1;
1794       case PIPE_VIDEO_CAP_NPOT_TEXTURES:
1795          return 1;
1796       case PIPE_VIDEO_CAP_MAX_TEMPORAL_LAYERS:
1797       {
1798             switch (u_reduce_video_profile(profile)) {
1799 #if VIDEO_CODEC_H264ENC
1800                case PIPE_VIDEO_FORMAT_MPEG4_AVC:
1801                   return D3D12_VIDEO_ENC_H264_MAX_TEMPORAL_LAYERS;
1802 #endif
1803 #if VIDEO_CODEC_H265ENC
1804                case PIPE_VIDEO_FORMAT_HEVC:
1805                   return D3D12_VIDEO_ENC_HEVC_MAX_TEMPORAL_LAYERS;
1806 #endif
1807 #if VIDEO_CODEC_AV1ENC
1808                case PIPE_VIDEO_FORMAT_AV1:
1809                   return D3D12_VIDEO_ENC_AV1_MAX_TEMPORAL_LAYERS;
1810 #endif
1811                default:
1812                   unreachable("Unsupported pipe_video_format");
1813             }
1814       } break;
1815       case PIPE_VIDEO_CAP_ENC_SUPPORTS_FEEDBACK_METADATA:
1816          return (PIPE_VIDEO_FEEDBACK_METADATA_TYPE_BITSTREAM_SIZE |
1817                  PIPE_VIDEO_FEEDBACK_METADATA_TYPE_ENCODE_RESULT |
1818                  PIPE_VIDEO_FEEDBACK_METADATA_TYPE_CODEC_UNIT_LOCATION |
1819                  PIPE_VIDEO_FEEDBACK_METADATA_TYPE_MAX_FRAME_SIZE_OVERFLOW |
1820                  PIPE_VIDEO_FEEDBACK_METADATA_TYPE_MAX_SLICE_SIZE_OVERFLOW |
1821                  PIPE_VIDEO_FEEDBACK_METADATA_TYPE_AVERAGE_FRAME_QP);
1822       case PIPE_VIDEO_CAP_MAX_WIDTH:
1823       case PIPE_VIDEO_CAP_MAX_HEIGHT:
1824       case PIPE_VIDEO_CAP_MIN_WIDTH:
1825       case PIPE_VIDEO_CAP_MIN_HEIGHT:
1826       case PIPE_VIDEO_CAP_MAX_LEVEL:
1827       case PIPE_VIDEO_CAP_SUPPORTED:
1828       case PIPE_VIDEO_CAP_ENC_MAX_SLICES_PER_FRAME:
1829       case PIPE_VIDEO_CAP_ENC_SLICES_STRUCTURE:
1830       case PIPE_VIDEO_CAP_ENC_MAX_REFERENCES_PER_FRAME:
1831       case PIPE_VIDEO_CAP_ENC_HEVC_FEATURE_FLAGS:
1832       case PIPE_VIDEO_CAP_ENC_HEVC_BLOCK_SIZES:
1833       case PIPE_VIDEO_CAP_ENC_HEVC_PREDICTION_DIRECTION:
1834       case PIPE_VIDEO_CAP_ENC_AV1_FEATURE:
1835       case PIPE_VIDEO_CAP_ENC_AV1_FEATURE_EXT1:
1836       case PIPE_VIDEO_CAP_ENC_AV1_FEATURE_EXT2:
1837       case PIPE_VIDEO_CAP_ENC_SUPPORTS_TILE:
1838       case PIPE_VIDEO_CAP_ENC_SUPPORTS_MAX_FRAME_SIZE:
1839       case PIPE_VIDEO_CAP_ENC_QUALITY_LEVEL:
1840       case PIPE_VIDEO_CAP_ENC_MAX_TILE_ROWS:
1841       case PIPE_VIDEO_CAP_ENC_MAX_TILE_COLS:
1842       case PIPE_VIDEO_CAP_ENC_INTRA_REFRESH_MAX_DURATION:
1843       case PIPE_VIDEO_CAP_ENC_INTRA_REFRESH:
1844       case PIPE_VIDEO_CAP_ENC_H264_DISABLE_DBK_FILTER_MODES_SUPPORTED:
1845       case PIPE_VIDEO_CAP_ENC_H264_SUPPORTS_CABAC_ENCODE:
1846       case PIPE_VIDEO_CAP_ENC_ROI:
1847       case PIPE_VIDEO_CAP_ENC_SURFACE_ALIGNMENT:
1848       case PIPE_VIDEO_CAP_ENC_HEVC_RANGE_EXTENSION_SUPPORT:
1849       case PIPE_VIDEO_CAP_ENC_HEVC_RANGE_EXTENSION_FLAGS_SUPPORT:
1850       {
1851          if (d3d12_has_video_encode_support(pscreen,
1852                                             profile,
1853                                             maxLvlEncode,
1854                                             minResEncode,
1855                                             maxResEncode,
1856                                             alignResEncode,
1857                                             maxSlices,
1858                                             supportedSliceStructures,
1859                                             maxReferencesPerFrame,
1860                                             codec_specific_support,
1861                                             isRCMaxFrameSizeSupported,
1862                                             maxQualityLevels,
1863                                             max_tile_rows,
1864                                             max_tile_cols,
1865                                             maxIRDuration,
1866                                             roi_support)) {
1867 
1868             DXGI_FORMAT format = d3d12_convert_pipe_video_profile_to_dxgi_format(profile);
1869             auto pipeFmt = d3d12_get_pipe_format(format);
1870             bool formatSupported = pscreen->is_video_format_supported(pscreen, pipeFmt, profile, entrypoint);
1871             if (formatSupported) {
1872                if (param == PIPE_VIDEO_CAP_MAX_WIDTH) {
1873                   return maxResEncode.Width;
1874                } else if (param == PIPE_VIDEO_CAP_MAX_HEIGHT) {
1875                   return maxResEncode.Height;
1876                } else if (param == PIPE_VIDEO_CAP_MIN_WIDTH) {
1877                   return minResEncode.Width;
1878                } else if (param == PIPE_VIDEO_CAP_MIN_HEIGHT) {
1879                   return minResEncode.Height;
1880                } else if (param == PIPE_VIDEO_CAP_MAX_LEVEL) {
1881                   return maxLvlEncode;
1882                } else if (param == PIPE_VIDEO_CAP_SUPPORTED) {
1883                   return 1;
1884                } else if (param == PIPE_VIDEO_CAP_ENC_MAX_SLICES_PER_FRAME) {
1885                   return maxSlices;
1886                } else if (param == PIPE_VIDEO_CAP_ENC_SLICES_STRUCTURE) {
1887                   return supportedSliceStructures;
1888                } else if (param == PIPE_VIDEO_CAP_ENC_MAX_TILE_ROWS) {
1889                   return max_tile_rows;
1890                } else if (param == PIPE_VIDEO_CAP_ENC_MAX_TILE_COLS) {
1891                   return max_tile_cols;
1892                } else if(param == PIPE_VIDEO_CAP_ENC_H264_DISABLE_DBK_FILTER_MODES_SUPPORTED) {
1893                   return codec_specific_support.h264_support.disable_dbk_filter_mode_flags;
1894                } else if (param == PIPE_VIDEO_CAP_ENC_MAX_REFERENCES_PER_FRAME) {
1895                   return maxReferencesPerFrame;
1896                } else if (param == PIPE_VIDEO_CAP_ENC_INTRA_REFRESH_MAX_DURATION) {
1897                   return maxIRDuration;
1898                } else if (param == PIPE_VIDEO_CAP_ENC_INTRA_REFRESH) {
1899                   return (maxIRDuration == 0) ? 0 :
1900                          (PIPE_VIDEO_ENC_INTRA_REFRESH_ROW |
1901                           PIPE_VIDEO_ENC_INTRA_REFRESH_ADAPTIVE |
1902                           PIPE_VIDEO_ENC_INTRA_REFRESH_CYCLIC |
1903                           PIPE_VIDEO_ENC_INTRA_REFRESH_P_FRAME |
1904                           PIPE_VIDEO_ENC_INTRA_REFRESH_B_FRAME |
1905                           PIPE_VIDEO_ENC_INTRA_REFRESH_MULTI_REF);
1906                } else if (param == PIPE_VIDEO_CAP_ENC_SUPPORTS_MAX_FRAME_SIZE) {
1907                   return isRCMaxFrameSizeSupported;
1908                } else if (param == PIPE_VIDEO_CAP_ENC_HEVC_FEATURE_FLAGS) {
1909                   /* get_video_param sets hevc_features.bits.config_supported = 1
1910                      to distinguish between supported cap with all bits off and unsupported by driver
1911                      with value = 0
1912                   */
1913                   return codec_specific_support.hevc_support.hevc_features.value;
1914                } else if (param == PIPE_VIDEO_CAP_ENC_HEVC_BLOCK_SIZES) {
1915                   /* get_video_param sets hevc_block_sizes.bits.config_supported = 1
1916                      to distinguish between supported cap with all bits off and unsupported by driver
1917                      with value = 0
1918                   */
1919                   return codec_specific_support.hevc_support.hevc_block_sizes.value;
1920                } else if (param == PIPE_VIDEO_CAP_ENC_HEVC_RANGE_EXTENSION_SUPPORT) {
1921                   return codec_specific_support.hevc_support.hevc_range_ext.value;
1922                } else if (param == PIPE_VIDEO_CAP_ENC_HEVC_RANGE_EXTENSION_FLAGS_SUPPORT) {
1923                   return codec_specific_support.hevc_support.hevc_range_ext_flags.value;
1924                } else if (param == PIPE_VIDEO_CAP_ENC_H264_SUPPORTS_CABAC_ENCODE) {
1925                   return (codec_specific_support.h264_support.d3d12_caps.SupportFlags &
1926                      D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_H264_FLAG_CABAC_ENCODING_SUPPORT);
1927                } else if (param == PIPE_VIDEO_CAP_ENC_HEVC_PREDICTION_DIRECTION) {
1928                   if (PIPE_VIDEO_FORMAT_HEVC == u_reduce_video_profile(profile))
1929                      return codec_specific_support.hevc_support.prediction_direction;
1930                   return 0;
1931                }
1932                else if (param == PIPE_VIDEO_CAP_ENC_AV1_FEATURE) {
1933                  return codec_specific_support.av1_support.features.value;
1934                } else if (param == PIPE_VIDEO_CAP_ENC_AV1_FEATURE_EXT1) {
1935                  return codec_specific_support.av1_support.features_ext1.value;
1936                } else if (param == PIPE_VIDEO_CAP_ENC_AV1_FEATURE_EXT2) {
1937                  return codec_specific_support.av1_support.features_ext2.value;
1938                } else if(param == PIPE_VIDEO_CAP_ENC_SUPPORTS_TILE) {
1939                   return (profile == PIPE_VIDEO_PROFILE_AV1_MAIN) && (maxSlices != 0);
1940                } else if(param == PIPE_VIDEO_CAP_ENC_QUALITY_LEVEL) {
1941                   return maxQualityLevels;
1942                } else if(param == PIPE_VIDEO_CAP_ENC_ROI) {
1943                   assert(roi_support.bits.num_roi_regions <= PIPE_ENC_ROI_REGION_NUM_MAX);
1944                   return static_cast<int>(roi_support.value);
1945                } else if(param == PIPE_VIDEO_CAP_ENC_SURFACE_ALIGNMENT) {
1946                   return alignResEncode.value;
1947                }
1948             }
1949          } else if (param == PIPE_VIDEO_CAP_ENC_QUALITY_LEVEL) {
1950             return 1; // This needs to be 1 for backcompat of frontend/va calling for PIPE_VIDEO_CAP_ENC_QUALITY_LEVEL > 0
1951          }
1952          return 0;
1953       } break;
1954       case PIPE_VIDEO_CAP_PREFERED_FORMAT:
1955          return (profile == PIPE_VIDEO_PROFILE_UNKNOWN) ? PIPE_FORMAT_NV12 : d3d12_get_pipe_format(d3d12_convert_pipe_video_profile_to_dxgi_format(profile));
1956       case PIPE_VIDEO_CAP_PREFERS_INTERLACED:
1957          return false;
1958       case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED:
1959          return false;
1960       case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE:
1961          return true;
1962       case PIPE_VIDEO_CAP_SUPPORTS_CONTIGUOUS_PLANES_MAP:
1963          return true;
1964       case PIPE_VIDEO_CAP_ENC_RATE_CONTROL_QVBR:
1965       {
1966          D3D12_FEATURE_DATA_VIDEO_ENCODER_RATE_CONTROL_MODE capRateControlModeData =
1967          {
1968             0,
1969             d3d12_video_encoder_convert_codec_to_d3d12_enc_codec(profile),
1970             D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_QVBR,
1971             false
1972          };
1973 
1974          ComPtr<ID3D12VideoDevice3> spD3D12VideoDevice;
1975          struct d3d12_screen *pD3D12Screen = (struct d3d12_screen *) pscreen;
1976          if (FAILED(pD3D12Screen->dev->QueryInterface(IID_PPV_ARGS(spD3D12VideoDevice.GetAddressOf())))) {
1977             // No video encode support in underlying d3d12 device (needs ID3D12VideoDevice3)
1978             return 0;
1979          }
1980 
1981          if (SUCCEEDED(spD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_RATE_CONTROL_MODE, &capRateControlModeData, sizeof(capRateControlModeData)))
1982             && capRateControlModeData.IsSupported)
1983             return 1; // Driver returns QVBR support OK
1984 
1985          // No QVBR support
1986          return 0;
1987       } break;
1988       default:
1989          debug_printf("[d3d12_screen_get_video_param] unknown video param: %d\n", param);
1990          return 0;
1991    }
1992 }
1993 
1994 static int
d3d12_screen_get_video_param(struct pipe_screen * pscreen,enum pipe_video_profile profile,enum pipe_video_entrypoint entrypoint,enum pipe_video_cap param)1995 d3d12_screen_get_video_param(struct pipe_screen *pscreen,
1996                              enum pipe_video_profile profile,
1997                              enum pipe_video_entrypoint entrypoint,
1998                              enum pipe_video_cap param)
1999 {
2000    if (entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
2001       return d3d12_screen_get_video_param_decode(pscreen, profile, entrypoint, param);
2002    } else if (entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) {
2003       return d3d12_screen_get_video_param_encode(pscreen, profile, entrypoint, param);
2004    } else if (entrypoint == PIPE_VIDEO_ENTRYPOINT_PROCESSING) {
2005       return d3d12_screen_get_video_param_postproc(pscreen, profile, entrypoint, param);
2006    }
2007    return 0;
2008 }
2009 
2010 static bool
is_d3d12_video_encode_format_supported(struct pipe_screen * screen,pipe_format format,enum pipe_video_profile profile)2011 is_d3d12_video_encode_format_supported(struct pipe_screen *screen,
2012                                            pipe_format format,
2013                                            enum pipe_video_profile profile)
2014 {
2015 #if VIDEO_CODEC_H264ENC
2016    D3D12_VIDEO_ENCODER_PROFILE_H264 profH264 = {};
2017 #endif
2018 #if VIDEO_CODEC_H265ENC
2019    D3D12_VIDEO_ENCODER_PROFILE_HEVC profHEVC = {};
2020 #endif
2021 #if VIDEO_CODEC_AV1ENC
2022    D3D12_VIDEO_ENCODER_AV1_PROFILE profAV1 = {};
2023 #endif
2024    D3D12_FEATURE_DATA_VIDEO_ENCODER_INPUT_FORMAT capDataFmt = {};
2025    capDataFmt.NodeIndex = 0;
2026    capDataFmt.Codec = d3d12_video_encoder_convert_codec_to_d3d12_enc_codec(profile);
2027    capDataFmt.Format = d3d12_get_format(format);
2028    switch (u_reduce_video_profile(profile)) {
2029 #if VIDEO_CODEC_H264ENC
2030       case PIPE_VIDEO_FORMAT_MPEG4_AVC:
2031       {
2032          profH264 = d3d12_video_encoder_convert_profile_to_d3d12_enc_profile_h264(profile);
2033          capDataFmt.Profile.DataSize = sizeof(profH264);
2034          capDataFmt.Profile.pH264Profile = &profH264;
2035       } break;
2036 #endif
2037 #if VIDEO_CODEC_H265ENC
2038       case PIPE_VIDEO_FORMAT_HEVC:
2039       {
2040          profHEVC = d3d12_video_encoder_convert_profile_to_d3d12_enc_profile_hevc(profile);
2041          capDataFmt.Profile.DataSize = sizeof(profHEVC);
2042          capDataFmt.Profile.pHEVCProfile = &profHEVC;
2043       } break;
2044 #endif
2045 #if VIDEO_CODEC_AV1ENC
2046       case PIPE_VIDEO_FORMAT_AV1:
2047       {
2048          profAV1 = d3d12_video_encoder_convert_profile_to_d3d12_enc_profile_av1(profile);
2049          capDataFmt.Profile.DataSize = sizeof(profAV1);
2050          capDataFmt.Profile.pAV1Profile = &profAV1;
2051       } break;
2052 #endif
2053       default:
2054       {
2055          unreachable("Unsupported pipe_video_format");
2056       } break;
2057    }
2058    ComPtr<ID3D12VideoDevice3> spD3D12VideoDevice;
2059    struct d3d12_screen *pD3D12Screen = (struct d3d12_screen *) screen;
2060    if (FAILED(pD3D12Screen->dev->QueryInterface(IID_PPV_ARGS(spD3D12VideoDevice.GetAddressOf())))) {
2061       // No video encode support in underlying d3d12 device (needs ID3D12VideoDevice3)
2062       return false;
2063    }
2064    HRESULT hr = spD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_INPUT_FORMAT,
2065                                                          &capDataFmt,
2066                                                          sizeof(capDataFmt));
2067    return SUCCEEDED(hr) && capDataFmt.IsSupported;
2068 }
2069 
2070 static bool
is_d3d12_video_decode_format_supported(struct pipe_screen * screen,pipe_format format,enum pipe_video_profile profile)2071 is_d3d12_video_decode_format_supported(struct pipe_screen *screen,
2072                                        pipe_format format,
2073                                        enum pipe_video_profile profile)
2074 {
2075    ComPtr<ID3D12VideoDevice> spD3D12VideoDevice;
2076    struct d3d12_screen *pD3D12Screen = (struct d3d12_screen *) screen;
2077    if (FAILED(pD3D12Screen->dev->QueryInterface(IID_PPV_ARGS(spD3D12VideoDevice.GetAddressOf()))))
2078       return false; // No video decode support in underlying d3d12 device (needs ID3D12VideoDevice)
2079 
2080    GUID decodeGUID = d3d12_video_decoder_convert_pipe_video_profile_to_d3d12_profile(profile);
2081    GUID emptyGUID = {};
2082    assert (decodeGUID != emptyGUID);
2083 
2084    D3D12_VIDEO_DECODE_CONFIGURATION decoderConfig = { decodeGUID,
2085                                                       D3D12_BITSTREAM_ENCRYPTION_TYPE_NONE,
2086                                                       D3D12_VIDEO_FRAME_CODED_INTERLACE_TYPE_NONE };
2087 
2088    D3D12_FEATURE_DATA_VIDEO_DECODE_FORMAT_COUNT decodeFormatCount = {0 /* NodeIndex*/, decoderConfig };
2089    if(FAILED(spD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_DECODE_FORMAT_COUNT,
2090                                                         &decodeFormatCount,
2091                                                         sizeof(decodeFormatCount))))
2092       return false;
2093 
2094     std::vector<DXGI_FORMAT> supportedDecodeFormats;
2095     supportedDecodeFormats.resize(decodeFormatCount.FormatCount);
2096 
2097     D3D12_FEATURE_DATA_VIDEO_DECODE_FORMATS decodeFormats =
2098     {
2099         0, // NodeIndex
2100         decoderConfig,
2101         static_cast<UINT>(supportedDecodeFormats.size()),
2102         supportedDecodeFormats.data()
2103     };
2104 
2105    if(FAILED(spD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_DECODE_FORMATS,
2106                                                          &decodeFormats,
2107                                                          sizeof(decodeFormats))))
2108       return false;
2109 
2110    DXGI_FORMAT requestedDXGIFormat = d3d12_get_format(format);
2111    for (DXGI_FORMAT fmt : supportedDecodeFormats)
2112       if (fmt == requestedDXGIFormat)
2113          return true;
2114    return false;
2115 }
2116 
2117 static bool
is_d3d12_video_process_format_supported(struct pipe_screen * screen,pipe_format format)2118 is_d3d12_video_process_format_supported(struct pipe_screen *screen,
2119                                         pipe_format format)
2120 {
2121    // Return both VPBlit support and format is in known list
2122    return (screen->get_video_param(screen,
2123                         PIPE_VIDEO_PROFILE_UNKNOWN,
2124                         PIPE_VIDEO_ENTRYPOINT_PROCESSING,
2125                         PIPE_VIDEO_CAP_SUPPORTED))
2126    &&
2127    ((format == PIPE_FORMAT_NV12) || (format == PIPE_FORMAT_P010)
2128       || (format == PIPE_FORMAT_R8G8B8A8_UNORM) || (format == PIPE_FORMAT_R8G8B8A8_UINT)
2129       || (format == PIPE_FORMAT_R8G8B8X8_UNORM) || (format == PIPE_FORMAT_R8G8B8X8_UINT));
2130 }
2131 
2132 static bool
is_d3d12_video_allowed_format(enum pipe_format format,enum pipe_video_entrypoint entrypoint)2133 is_d3d12_video_allowed_format(enum pipe_format format, enum pipe_video_entrypoint entrypoint)
2134 {
2135    if (entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
2136       return ((format == PIPE_FORMAT_NV12) || (format == PIPE_FORMAT_P010));
2137    } else if (entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) {
2138       return ((format == PIPE_FORMAT_NV12) || (format == PIPE_FORMAT_P010) || (format == PIPE_FORMAT_AYUV));
2139    } else if (entrypoint == PIPE_VIDEO_ENTRYPOINT_PROCESSING) {
2140       return (format == PIPE_FORMAT_NV12) || (format == PIPE_FORMAT_P010)
2141          || (format == PIPE_FORMAT_R8G8B8A8_UNORM) || (format == PIPE_FORMAT_R8G8B8A8_UINT)
2142          || (format == PIPE_FORMAT_R8G8B8X8_UNORM) || (format == PIPE_FORMAT_R8G8B8X8_UINT);
2143    }
2144    return false;
2145 }
2146 
2147 static bool
d3d12_video_buffer_is_format_supported(struct pipe_screen * screen,enum pipe_format format,enum pipe_video_profile profile,enum pipe_video_entrypoint entrypoint)2148 d3d12_video_buffer_is_format_supported(struct pipe_screen *screen,
2149                                        enum pipe_format format,
2150                                        enum pipe_video_profile profile,
2151                                        enum pipe_video_entrypoint entrypoint)
2152 {
2153    // Check in allowed list of formats first
2154    if(!is_d3d12_video_allowed_format(format, entrypoint))
2155       return false;
2156 
2157    // If the VA frontend asks for all profiles, assign
2158    // a default profile based on the bitdepth
2159    if(u_reduce_video_profile(profile) == PIPE_VIDEO_FORMAT_UNKNOWN)
2160    {
2161       profile = (format == PIPE_FORMAT_P010) ? PIPE_VIDEO_PROFILE_HEVC_MAIN_10 : PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN;
2162    }
2163 
2164    // Then check is the underlying driver supports the allowed formats
2165    if (entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
2166       return is_d3d12_video_decode_format_supported(screen, format, profile);
2167    } else if (entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) {
2168       return is_d3d12_video_encode_format_supported(screen, format, profile);
2169    } else if (entrypoint == PIPE_VIDEO_ENTRYPOINT_PROCESSING) {
2170       return is_d3d12_video_process_format_supported(screen, format);
2171    }
2172    return false;
2173 }
2174 
2175 void
d3d12_screen_video_init(struct pipe_screen * pscreen)2176 d3d12_screen_video_init(struct pipe_screen *pscreen)
2177 {
2178    pscreen->get_video_param = d3d12_screen_get_video_param;
2179    pscreen->is_video_format_supported = d3d12_video_buffer_is_format_supported;
2180 }
2181