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