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