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