d3d12: Extend video screen AV1 encode tile support checking
authorSil Vilerino <sivileri@microsoft.com>
Tue, 29 Aug 2023 01:01:21 +0000 (21:01 -0400)
committerMarge Bot <emma+marge@anholt.net>
Wed, 6 Sep 2023 21:30:02 +0000 (21:30 +0000)
Add fallback case to take into account driver reported tile restrictions if
default hardcoded tile configurations are not supported by driver

Reviewed-by: Tanner Van De Walle <tvandewalle@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25070>

src/gallium/drivers/d3d12/d3d12_video_screen.cpp

index a39c335..0976de5 100644 (file)
@@ -327,7 +327,7 @@ d3d12_video_encode_supported_tile_structures(const D3D12_VIDEO_ENCODER_CODEC &co
                                              ID3D12VideoDevice3 *pD3D12VideoDevice,
                                              D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC maxRes,
                                              uint32_t& supportedSliceStructures, // out
-                                             uint32_t& tile_size_bytes_minus1 // out
+                                             D3D12_VIDEO_ENCODER_AV1_FRAME_SUBREGION_LAYOUT_CONFIG_SUPPORT& av1TileSupport // out
 )
 {
    // Assume no support and then add as queries succeed
@@ -342,28 +342,70 @@ d3d12_video_encode_supported_tile_structures(const D3D12_VIDEO_ENCODER_CODEC &co
    capDataTilesSupport.Profile = profile;
    capDataTilesSupport.Level = level;
    capDataTilesSupport.FrameResolution = maxRes; // Query for worst case resolution
-   D3D12_VIDEO_ENCODER_AV1_FRAME_SUBREGION_LAYOUT_CONFIG_SUPPORT av1TileSupport = { };
+   av1TileSupport = { };
    capDataTilesSupport.CodecSupport.DataSize = sizeof(av1TileSupport);
    capDataTilesSupport.CodecSupport.pAV1Support = &av1TileSupport;
    av1TileSupport.Use128SuperBlocks = false; // return units in 64x64 default size
+   constexpr UINT superBlockSize = 64u;
 
-   capDataTilesSupport.SubregionMode =
-      D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_GRID_PARTITION;
-   HRESULT hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_CONFIG,
-                                                       &capDataTilesSupport,
-                                                       sizeof(capDataTilesSupport));
-   if(SUCCEEDED(hr) && capDataTilesSupport.IsSupported)
-      supportedSliceStructures |= (PIPE_VIDEO_CAP_SLICE_STRUCTURE_POWER_OF_TWO_ROWS | PIPE_VIDEO_CAP_SLICE_STRUCTURE_EQUAL_ROWS | PIPE_VIDEO_CAP_SLICE_STRUCTURE_EQUAL_MULTI_ROWS);
-
-   capDataTilesSupport.SubregionMode =
-      D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_CONFIGURABLE_GRID_PARTITION;
-   hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_CONFIG,
-                                                       &capDataTilesSupport,
-                                                       sizeof(capDataTilesSupport));
-   if(SUCCEEDED(hr) && capDataTilesSupport.IsSupported)
-      supportedSliceStructures |= (PIPE_VIDEO_CAP_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS | PIPE_VIDEO_CAP_SLICE_STRUCTURE_ARBITRARY_ROWS);
-
-   tile_size_bytes_minus1 = av1TileSupport.TileSizeBytesMinus1;
+   {
+      capDataTilesSupport.SubregionMode = D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_GRID_PARTITION;
+      // Try with simple one tile request
+      av1TileSupport.TilesConfiguration.ColCount = 1;
+      av1TileSupport.TilesConfiguration.RowCount = 1;
+      av1TileSupport.TilesConfiguration.ColWidths[0] = (capDataTilesSupport.FrameResolution.Width / superBlockSize);
+      av1TileSupport.TilesConfiguration.RowHeights[0] = (capDataTilesSupport.FrameResolution.Height / superBlockSize);
+      HRESULT hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_CONFIG,
+                                                  &capDataTilesSupport,
+                                                  sizeof(capDataTilesSupport));
+      if(SUCCEEDED(hr) && !capDataTilesSupport.IsSupported) {
+         // Try with minimum driver indicated params for the given resolution
+         // (ie. this could happen for high resolutions like 8K where AV1 max_tile_width (4096) is exceeded)
+         av1TileSupport.TilesConfiguration.ColCount = std::max(av1TileSupport.MinTileCols, 1u);
+         av1TileSupport.TilesConfiguration.RowCount = std::max(av1TileSupport.MinTileRows, 1u);
+         hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_CONFIG,
+                                                  &capDataTilesSupport,
+                                                  sizeof(capDataTilesSupport));
+      }
+
+      if(SUCCEEDED(hr) && capDataTilesSupport.IsSupported)
+         supportedSliceStructures |= (PIPE_VIDEO_CAP_SLICE_STRUCTURE_POWER_OF_TWO_ROWS |
+                                      PIPE_VIDEO_CAP_SLICE_STRUCTURE_EQUAL_ROWS |
+                                      PIPE_VIDEO_CAP_SLICE_STRUCTURE_EQUAL_MULTI_ROWS);
+   }
+
+   {
+      capDataTilesSupport.SubregionMode = D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_CONFIGURABLE_GRID_PARTITION;
+      // Try with simple one tile request
+      av1TileSupport.TilesConfiguration.ColCount = 1;
+      av1TileSupport.TilesConfiguration.RowCount = 1;
+      av1TileSupport.TilesConfiguration.ColWidths[0] = capDataTilesSupport.FrameResolution.Width;
+      av1TileSupport.TilesConfiguration.RowHeights[0] = capDataTilesSupport.FrameResolution.Height;
+      HRESULT hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_CONFIG,
+                                                  &capDataTilesSupport,
+                                                  sizeof(capDataTilesSupport));
+      if(SUCCEEDED(hr) && !capDataTilesSupport.IsSupported) {
+         // Try with minimum driver indicated params for the given resolution
+         // (ie. this could happen for high resolutions like 8K where AV1 max_tile_width (4096) is exceeded)
+         av1TileSupport.TilesConfiguration.ColCount = std::max(av1TileSupport.MinTileCols, 1u);
+         av1TileSupport.TilesConfiguration.RowCount = std::max(av1TileSupport.MinTileRows, 1u);
+         // Try for uniform grid tiles
+         UINT tileWPixel = capDataTilesSupport.FrameResolution.Width / av1TileSupport.TilesConfiguration.ColCount;
+         UINT tileHPixel = capDataTilesSupport.FrameResolution.Height / av1TileSupport.TilesConfiguration.RowCount;
+         for (UINT i = 0; i < av1TileSupport.TilesConfiguration.ColCount; i++)
+            av1TileSupport.TilesConfiguration.ColWidths[i] = (tileWPixel / superBlockSize);
+         for (UINT j = 0; j < av1TileSupport.TilesConfiguration.RowCount; j++)
+            av1TileSupport.TilesConfiguration.RowHeights[j] = (tileHPixel / superBlockSize);
+
+         hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_CONFIG,
+                                                  &capDataTilesSupport,
+                                                  sizeof(capDataTilesSupport));
+      }
+
+      if(SUCCEEDED(hr) && capDataTilesSupport.IsSupported)
+         supportedSliceStructures |= (PIPE_VIDEO_CAP_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS |
+                                      PIPE_VIDEO_CAP_SLICE_STRUCTURE_ARBITRARY_ROWS);
+   }
 }
 #endif
 
@@ -459,11 +501,9 @@ d3d12_video_encode_support_caps(const D3D12_VIDEO_ENCODER_CODEC &argTargetCodec,
                                 DXGI_FORMAT encodeFormat,
                                 ID3D12VideoDevice3 *pD3D12VideoDevice,
                                 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT codecSupport,
-                                D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE requestedSliceMode,
                                 D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT1 &capEncoderSupportData1,
                                 D3D12_FEATURE_DATA_VIDEO_ENCODER_RESOLUTION_SUPPORT_LIMITS &resolutionDepCaps)
 {
-   capEncoderSupportData1 = {};
    capEncoderSupportData1.NodeIndex = 0;
    capEncoderSupportData1.Codec = argTargetCodec;
    capEncoderSupportData1.InputFormat = encodeFormat;
@@ -478,13 +518,6 @@ d3d12_video_encode_support_caps(const D3D12_VIDEO_ENCODER_CODEC &argTargetCodec,
    capEncoderSupportData1.ResolutionsListCount = 1;
    capEncoderSupportData1.pResolutionList = &maxResolution;
    capEncoderSupportData1.MaxReferenceFramesInDPB = 1;
-#if D3D12_PREVIEW_SDK_VERSION >= 711
-   D3D12_VIDEO_ENCODER_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_SLICES sliceData = { };
-   // Assume single tile for feature query support  / entrypoint enumeration purposes
-   D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_TILES tileData = { };
-   tileData.ColCount = 1;
-   tileData.RowCount = 1;
-#endif
    /*
       All codec structures must be declared outside the switch statement to be
       present in memory (stack scope) when calling CheckFeatureSupport below
@@ -515,11 +548,6 @@ d3d12_video_encode_support_caps(const D3D12_VIDEO_ENCODER_CODEC &argTargetCodec,
          capEncoderSupportData1.CodecGopSequence.DataSize = sizeof(h264Gop);
          capEncoderSupportData1.CodecConfiguration.DataSize = sizeof(h264Config);
          capEncoderSupportData1.CodecConfiguration.pH264Config = &h264Config;
-         capEncoderSupportData1.SubregionFrameEncoding = requestedSliceMode;
-#if D3D12_PREVIEW_SDK_VERSION >= 711
-         capEncoderSupportData1.SubregionFrameEncodingData.DataSize = sizeof(sliceData);
-         capEncoderSupportData1.SubregionFrameEncodingData.pSlicesPartition_H264 = &sliceData;
-#endif
       } break;
 
       case D3D12_VIDEO_ENCODER_CODEC_HEVC:
@@ -547,11 +575,6 @@ d3d12_video_encode_support_caps(const D3D12_VIDEO_ENCODER_CODEC &argTargetCodec,
          capEncoderSupportData1.CodecGopSequence.DataSize = sizeof(hevcGop);
          capEncoderSupportData1.CodecConfiguration.DataSize = sizeof(hevcConfig);
          capEncoderSupportData1.CodecConfiguration.pHEVCConfig = &hevcConfig;
-         capEncoderSupportData1.SubregionFrameEncoding = requestedSliceMode;
-#if D3D12_PREVIEW_SDK_VERSION >= 711
-         capEncoderSupportData1.SubregionFrameEncodingData.DataSize = sizeof(sliceData);
-         capEncoderSupportData1.SubregionFrameEncodingData.pSlicesPartition_HEVC = &sliceData;
-#endif
       } break;
 
 #if D3D12_PREVIEW_SDK_VERSION >= 711
@@ -583,10 +606,6 @@ d3d12_video_encode_support_caps(const D3D12_VIDEO_ENCODER_CODEC &argTargetCodec,
          av1Config.FeatureFlags = av1CodecSupport.RequiredFeatureFlags;
          capEncoderSupportData1.CodecConfiguration.DataSize = sizeof(av1Config);
          capEncoderSupportData1.CodecConfiguration.pAV1Config = &av1Config;
-         capEncoderSupportData1.SubregionFrameEncoding = requestedSliceMode;
-         capEncoderSupportData1.SubregionFrameEncodingData.DataSize = sizeof(tileData);
-         capEncoderSupportData1.SubregionFrameEncodingData.pTilesPartition_AV1 = &tileData;
-
       } break;
 #endif
       default:
@@ -794,16 +813,21 @@ d3d12_has_video_encode_support(struct pipe_screen *pscreen,
                                                                                      profile,
                                                                                      level,
                                                                                      spD3D12VideoDevice.Get());
-            D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT1 capEncoderSupportData1;
+            D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT1 capEncoderSupportData1 = {};
             D3D12_FEATURE_DATA_VIDEO_ENCODER_RESOLUTION_SUPPORT_LIMITS resolutionDepCaps;
+            capEncoderSupportData1.SubregionFrameEncoding = (supportedSliceStructures == PIPE_VIDEO_CAP_SLICE_STRUCTURE_NONE) ?
+                                                             D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_FULL_FRAME :
+                                                             D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_PARTITIONING_SUBREGIONS_PER_FRAME;
+#if D3D12_PREVIEW_SDK_VERSION >= 711
+            D3D12_VIDEO_ENCODER_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_SLICES sliceData = { };
+            capEncoderSupportData1.SubregionFrameEncodingData.DataSize = sizeof(sliceData);
+            capEncoderSupportData1.SubregionFrameEncodingData.pSlicesPartition_H264 = &sliceData;
+#endif
             supportsProfile = supportsProfile && d3d12_video_encode_support_caps(codecDesc,
                                                                                  maxRes,
                                                                                  encodeFormat,
                                                                                  spD3D12VideoDevice.Get(),
                                                                                  d3d12_codec_support,
-                                                                                 (supportedSliceStructures == PIPE_VIDEO_CAP_SLICE_STRUCTURE_NONE) ?
-                                                                                    D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_FULL_FRAME
-                                                                                       : D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_PARTITIONING_SUBREGIONS_PER_FRAME,
                                                                                  capEncoderSupportData1,
                                                                                  resolutionDepCaps);
             if (supportedSliceStructures == PIPE_VIDEO_CAP_SLICE_STRUCTURE_NONE)
@@ -957,16 +981,21 @@ d3d12_has_video_encode_support(struct pipe_screen *pscreen,
                supportsProfile = supportsProfile &&
                                  d3d12_video_encode_supported_resolution_range(codecDesc, minRes, maxRes, spD3D12VideoDevice.Get());
 
-               D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT1 capEncoderSupportData1;
+               D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT1 capEncoderSupportData1 = {};
                D3D12_FEATURE_DATA_VIDEO_ENCODER_RESOLUTION_SUPPORT_LIMITS resolutionDepCaps;
+               capEncoderSupportData1.SubregionFrameEncoding = (supportedSliceStructures == PIPE_VIDEO_CAP_SLICE_STRUCTURE_NONE) ?
+                                                                D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_FULL_FRAME :
+                                                                D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_PARTITIONING_SUBREGIONS_PER_FRAME;
+#if D3D12_PREVIEW_SDK_VERSION >= 711
+               D3D12_VIDEO_ENCODER_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_SLICES sliceData = { };
+               capEncoderSupportData1.SubregionFrameEncodingData.DataSize = sizeof(sliceData);
+               capEncoderSupportData1.SubregionFrameEncodingData.pSlicesPartition_HEVC = &sliceData;
+#endif
                supportsProfile = supportsProfile && d3d12_video_encode_support_caps(codecDesc,
                                                                                     maxRes,
                                                                                     encodeFormat,
                                                                                     spD3D12VideoDevice.Get(),
                                                                                     d3d12_codec_support,
-                                                                                    (supportedSliceStructures == PIPE_VIDEO_CAP_SLICE_STRUCTURE_NONE) ?
-                                                                                       D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_FULL_FRAME
-                                                                                          : D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_PARTITIONING_SUBREGIONS_PER_FRAME,
                                                                                     capEncoderSupportData1,
                                                                                     resolutionDepCaps);
                if (supportedSliceStructures == PIPE_VIDEO_CAP_SLICE_STRUCTURE_NONE)
@@ -1178,30 +1207,34 @@ d3d12_has_video_encode_support(struct pipe_screen *pscreen,
                supportsProfile = supportsProfile &&
                                  d3d12_video_encode_supported_resolution_range(codecDesc, minRes, maxRes, spD3D12VideoDevice.Get());
 
-               uint32_t tile_size_bytes_minus1 = 0;
+               D3D12_VIDEO_ENCODER_AV1_FRAME_SUBREGION_LAYOUT_CONFIG_SUPPORT av1TileSupport = {};
                d3d12_video_encode_supported_tile_structures(codecDesc,
                                                             profDesc,
                                                             maxLvl,
                                                             spD3D12VideoDevice.Get(),
                                                             maxRes,
-                                                            supportedSliceStructures, // out
-                                                            tile_size_bytes_minus1 // out
+                                                            supportedSliceStructures,
+                                                            av1TileSupport // out
                                                          );
                // Cannot pass pipe 2 bit-field as reference, use aux variable instead.
-               codecSupport.av1_support.features_ext2.bits.tile_size_bytes_minus1 = tile_size_bytes_minus1;
+               codecSupport.av1_support.features_ext2.bits.tile_size_bytes_minus1 = av1TileSupport.TileSizeBytesMinus1;
 
                DXGI_FORMAT encodeFormat = d3d12_convert_pipe_video_profile_to_dxgi_format(profile);
 
-               D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT1 capEncoderSupportData1;
+               D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT1 capEncoderSupportData1 = {};
                D3D12_FEATURE_DATA_VIDEO_ENCODER_RESOLUTION_SUPPORT_LIMITS resolutionDepCaps;
+               capEncoderSupportData1.SubregionFrameEncoding = (supportedSliceStructures == PIPE_VIDEO_CAP_SLICE_STRUCTURE_NONE) ?
+                                                                D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_FULL_FRAME :
+                                                                D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_GRID_PARTITION;
+
+               capEncoderSupportData1.SubregionFrameEncodingData.DataSize = sizeof(av1TileSupport.TilesConfiguration);
+               capEncoderSupportData1.SubregionFrameEncodingData.pTilesPartition_AV1 = &av1TileSupport.TilesConfiguration;
+
                supportsProfile = supportsProfile && d3d12_video_encode_support_caps(codecDesc,
                                                                                     maxRes,
                                                                                     encodeFormat,
                                                                                     spD3D12VideoDevice.Get(),
                                                                                     d3d12_codec_support,
-                                                                                    (supportedSliceStructures == PIPE_VIDEO_CAP_SLICE_STRUCTURE_NONE) ?
-                                                                                       D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_FULL_FRAME
-                                                                                          : D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_GRID_PARTITION,
                                                                                     capEncoderSupportData1,
                                                                                     resolutionDepCaps);
                if (supportedSliceStructures == PIPE_VIDEO_CAP_SLICE_STRUCTURE_NONE)