• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2021 Red Hat
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 "anv_private.h"
25 
26 #include "av1_tables.h"
27 #include "vk_video/vulkan_video_codecs_common.h"
28 
29 VkResult
anv_CreateVideoSessionKHR(VkDevice _device,const VkVideoSessionCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkVideoSessionKHR * pVideoSession)30 anv_CreateVideoSessionKHR(VkDevice _device,
31                            const VkVideoSessionCreateInfoKHR *pCreateInfo,
32                            const VkAllocationCallbacks *pAllocator,
33                            VkVideoSessionKHR *pVideoSession)
34 {
35    ANV_FROM_HANDLE(anv_device, device, _device);
36 
37    struct anv_video_session *vid =
38       vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*vid), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
39    if (!vid)
40       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
41 
42    memset(vid, 0, sizeof(struct anv_video_session));
43 
44    VkResult result = vk_video_session_init(&device->vk,
45                                            &vid->vk,
46                                            pCreateInfo);
47    if (result != VK_SUCCESS) {
48       vk_free2(&device->vk.alloc, pAllocator, vid);
49       return result;
50    }
51 
52    *pVideoSession = anv_video_session_to_handle(vid);
53    return VK_SUCCESS;
54 }
55 
56 void
anv_DestroyVideoSessionKHR(VkDevice _device,VkVideoSessionKHR _session,const VkAllocationCallbacks * pAllocator)57 anv_DestroyVideoSessionKHR(VkDevice _device,
58                            VkVideoSessionKHR _session,
59                            const VkAllocationCallbacks *pAllocator)
60 {
61    ANV_FROM_HANDLE(anv_device, device, _device);
62    ANV_FROM_HANDLE(anv_video_session, vid, _session);
63    if (!_session)
64       return;
65 
66    vk_object_base_finish(&vid->vk.base);
67    vk_free2(&device->vk.alloc, pAllocator, vid);
68 }
69 
70 VkResult
anv_CreateVideoSessionParametersKHR(VkDevice _device,const VkVideoSessionParametersCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkVideoSessionParametersKHR * pVideoSessionParameters)71 anv_CreateVideoSessionParametersKHR(VkDevice _device,
72                                      const VkVideoSessionParametersCreateInfoKHR *pCreateInfo,
73                                      const VkAllocationCallbacks *pAllocator,
74                                      VkVideoSessionParametersKHR *pVideoSessionParameters)
75 {
76    ANV_FROM_HANDLE(anv_device, device, _device);
77    ANV_FROM_HANDLE(anv_video_session, vid, pCreateInfo->videoSession);
78    ANV_FROM_HANDLE(anv_video_session_params, templ, pCreateInfo->videoSessionParametersTemplate);
79    struct anv_video_session_params *params =
80       vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*params), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
81    if (!params)
82       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
83 
84    VkResult result = vk_video_session_parameters_init(&device->vk,
85                                                       &params->vk,
86                                                       &vid->vk,
87                                                       templ ? &templ->vk : NULL,
88                                                       pCreateInfo);
89    if (result != VK_SUCCESS) {
90       vk_free2(&device->vk.alloc, pAllocator, params);
91       return result;
92    }
93 
94    *pVideoSessionParameters = anv_video_session_params_to_handle(params);
95    return VK_SUCCESS;
96 }
97 
98 void
anv_DestroyVideoSessionParametersKHR(VkDevice _device,VkVideoSessionParametersKHR _params,const VkAllocationCallbacks * pAllocator)99 anv_DestroyVideoSessionParametersKHR(VkDevice _device,
100                                       VkVideoSessionParametersKHR _params,
101                                       const VkAllocationCallbacks *pAllocator)
102 {
103    ANV_FROM_HANDLE(anv_device, device, _device);
104    ANV_FROM_HANDLE(anv_video_session_params, params, _params);
105    if (!_params)
106       return;
107    vk_video_session_parameters_finish(&device->vk, &params->vk);
108    vk_free2(&device->vk.alloc, pAllocator, params);
109 }
110 
111 VkResult
anv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice,const VkVideoProfileInfoKHR * pVideoProfile,VkVideoCapabilitiesKHR * pCapabilities)112 anv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice,
113                                            const VkVideoProfileInfoKHR *pVideoProfile,
114                                            VkVideoCapabilitiesKHR *pCapabilities)
115 {
116    ANV_FROM_HANDLE(anv_physical_device, pdevice, physicalDevice);
117 
118    pCapabilities->minBitstreamBufferOffsetAlignment = 32;
119    pCapabilities->minBitstreamBufferSizeAlignment = 1;
120    pCapabilities->pictureAccessGranularity.width = ANV_MB_WIDTH;
121    pCapabilities->pictureAccessGranularity.height = ANV_MB_HEIGHT;
122    pCapabilities->minCodedExtent.width = ANV_MB_WIDTH;
123    pCapabilities->minCodedExtent.height = ANV_MB_HEIGHT;
124    pCapabilities->maxCodedExtent.width = 4096;
125    pCapabilities->maxCodedExtent.height = 4096;
126    pCapabilities->flags = VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR;
127 
128    struct VkVideoDecodeCapabilitiesKHR *dec_caps = (struct VkVideoDecodeCapabilitiesKHR *)
129       vk_find_struct(pCapabilities->pNext, VIDEO_DECODE_CAPABILITIES_KHR);
130 
131    if (dec_caps)
132       dec_caps->flags = VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR;
133 
134    /* H264 allows different luma and chroma bit depths */
135    if (pVideoProfile->lumaBitDepth != pVideoProfile->chromaBitDepth)
136       return VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR;
137 
138    if (pVideoProfile->chromaSubsampling != VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR)
139       return VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR;
140 
141    switch (pVideoProfile->videoCodecOperation) {
142    case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR: {
143       struct VkVideoDecodeH264CapabilitiesKHR *ext = (struct VkVideoDecodeH264CapabilitiesKHR *)
144          vk_find_struct(pCapabilities->pNext, VIDEO_DECODE_H264_CAPABILITIES_KHR);
145 
146       if (pVideoProfile->lumaBitDepth != VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR)
147          return VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR;
148 
149       pCapabilities->maxDpbSlots = ANV_VIDEO_H264_MAX_DPB_SLOTS;
150       pCapabilities->maxActiveReferencePictures = ANV_VIDEO_H264_MAX_NUM_REF_FRAME;
151       pCapabilities->pictureAccessGranularity.width = ANV_MB_WIDTH;
152       pCapabilities->pictureAccessGranularity.height = ANV_MB_HEIGHT;
153       pCapabilities->minCodedExtent.width = ANV_MB_WIDTH;
154       pCapabilities->minCodedExtent.height = ANV_MB_HEIGHT;
155 
156       ext->fieldOffsetGranularity.x = 0;
157       ext->fieldOffsetGranularity.y = 0;
158       ext->maxLevelIdc = STD_VIDEO_H264_LEVEL_IDC_5_1;
159       strcpy(pCapabilities->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_EXTENSION_NAME);
160       pCapabilities->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_SPEC_VERSION;
161       break;
162    }
163    case VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR: {
164 
165       const struct VkVideoDecodeAV1ProfileInfoKHR *av1_profile =
166          vk_find_struct_const(pVideoProfile->pNext, VIDEO_DECODE_AV1_PROFILE_INFO_KHR);
167 
168       if (av1_profile->stdProfile != STD_VIDEO_AV1_PROFILE_MAIN)
169          return VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR;
170 
171       if (pVideoProfile->lumaBitDepth != VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR &&
172           pVideoProfile->lumaBitDepth != VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR)
173          return VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR;
174 
175       struct VkVideoDecodeAV1CapabilitiesKHR *ext = (struct VkVideoDecodeAV1CapabilitiesKHR *)
176          vk_find_struct(pCapabilities->pNext, VIDEO_DECODE_AV1_CAPABILITIES_KHR);
177 
178       ext->maxLevel = STD_VIDEO_AV1_LEVEL_6_0;
179 
180       pCapabilities->maxDpbSlots = 8;
181       pCapabilities->maxActiveReferencePictures = 7;
182       dec_caps->flags |= VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR;
183 
184       strcpy(pCapabilities->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_EXTENSION_NAME);
185       pCapabilities->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_SPEC_VERSION;
186       break;
187    }
188    case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR: {
189       struct VkVideoDecodeH265CapabilitiesKHR *ext = (struct VkVideoDecodeH265CapabilitiesKHR *)
190          vk_find_struct(pCapabilities->pNext, VIDEO_DECODE_H265_CAPABILITIES_KHR);
191 
192       const struct VkVideoDecodeH265ProfileInfoKHR *h265_profile =
193          vk_find_struct_const(pVideoProfile->pNext,
194                               VIDEO_DECODE_H265_PROFILE_INFO_KHR);
195 
196       /* No hardware supports the scc extension profile */
197       if (h265_profile->stdProfileIdc != STD_VIDEO_H265_PROFILE_IDC_MAIN &&
198           h265_profile->stdProfileIdc != STD_VIDEO_H265_PROFILE_IDC_MAIN_10 &&
199           h265_profile->stdProfileIdc != STD_VIDEO_H265_PROFILE_IDC_MAIN_STILL_PICTURE &&
200           h265_profile->stdProfileIdc != STD_VIDEO_H265_PROFILE_IDC_FORMAT_RANGE_EXTENSIONS)
201          return VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR;
202 
203       /* Skylake only supports the main profile */
204       if (h265_profile->stdProfileIdc != STD_VIDEO_H265_PROFILE_IDC_MAIN &&
205           h265_profile->stdProfileIdc != STD_VIDEO_H265_PROFILE_IDC_MAIN_STILL_PICTURE &&
206           pdevice->info.platform <= INTEL_PLATFORM_SKL)
207          return VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR;
208 
209       /* Gfx10 and under don't support the range extension profile */
210       if (h265_profile->stdProfileIdc != STD_VIDEO_H265_PROFILE_IDC_MAIN &&
211           h265_profile->stdProfileIdc != STD_VIDEO_H265_PROFILE_IDC_MAIN_10 &&
212           h265_profile->stdProfileIdc != STD_VIDEO_H265_PROFILE_IDC_MAIN_STILL_PICTURE &&
213           pdevice->info.ver <= 10)
214          return VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR;
215 
216       if (pVideoProfile->lumaBitDepth != VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR &&
217           pVideoProfile->lumaBitDepth != VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR)
218          return VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR;
219 
220       pCapabilities->pictureAccessGranularity.width = ANV_MAX_H265_CTB_SIZE;
221       pCapabilities->pictureAccessGranularity.height = ANV_MAX_H265_CTB_SIZE;
222       pCapabilities->minCodedExtent.width = ANV_MAX_H265_CTB_SIZE;
223       pCapabilities->minCodedExtent.height = ANV_MAX_H265_CTB_SIZE;
224       pCapabilities->maxDpbSlots = ANV_VIDEO_H265_MAX_NUM_REF_FRAME;
225       pCapabilities->maxActiveReferencePictures = ANV_VIDEO_H265_HCP_NUM_REF_FRAME;
226 
227       ext->maxLevelIdc = STD_VIDEO_H265_LEVEL_IDC_6_2;
228 
229       strcpy(pCapabilities->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_EXTENSION_NAME);
230       pCapabilities->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_SPEC_VERSION;
231       break;
232    }
233    default:
234       break;
235    }
236 
237    struct VkVideoEncodeCapabilitiesKHR *enc_caps = (struct VkVideoEncodeCapabilitiesKHR *)
238       vk_find_struct(pCapabilities->pNext, VIDEO_ENCODE_CAPABILITIES_KHR);
239 
240    if (enc_caps) {
241       enc_caps->flags = 0;
242       enc_caps->rateControlModes = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DEFAULT_KHR |
243                                    VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR;
244       enc_caps->maxRateControlLayers = 1;
245       enc_caps->maxQualityLevels = 1;
246       enc_caps->encodeInputPictureGranularity.width = 32;
247       enc_caps->encodeInputPictureGranularity.height = 32;
248       enc_caps->supportedEncodeFeedbackFlags =
249          VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR |
250          VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR;
251    }
252 
253    switch (pVideoProfile->videoCodecOperation) {
254    case VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR: {
255       struct VkVideoEncodeH264CapabilitiesKHR *ext = (struct VkVideoEncodeH264CapabilitiesKHR *)
256          vk_find_struct(pCapabilities->pNext, VIDEO_ENCODE_H264_CAPABILITIES_KHR);
257 
258       if (ext) {
259          ext->flags = VK_VIDEO_ENCODE_H264_CAPABILITY_HRD_COMPLIANCE_BIT_KHR;
260          ext->maxLevelIdc = STD_VIDEO_H264_LEVEL_IDC_5_1;
261          ext->maxSliceCount = 1;
262          ext->maxPPictureL0ReferenceCount = 8;
263          ext->maxBPictureL0ReferenceCount = 8;
264          ext->maxL1ReferenceCount = 0;
265          ext->maxTemporalLayerCount = 0;
266          ext->expectDyadicTemporalLayerPattern = false;
267          ext->prefersGopRemainingFrames = 0;
268          ext->requiresGopRemainingFrames = 0;
269          ext->minQp = 10;
270          ext->maxQp = 51;
271       }
272 
273       pCapabilities->minBitstreamBufferOffsetAlignment = 32;
274       pCapabilities->minBitstreamBufferSizeAlignment = 4096;
275 
276       pCapabilities->maxDpbSlots = ANV_VIDEO_H264_MAX_NUM_REF_FRAME;
277       pCapabilities->maxActiveReferencePictures = ANV_VIDEO_H264_MAX_NUM_REF_FRAME;
278       pCapabilities->pictureAccessGranularity.width = ANV_MB_WIDTH;
279       pCapabilities->pictureAccessGranularity.height = ANV_MB_HEIGHT;
280       pCapabilities->minCodedExtent.width = ANV_MB_WIDTH;
281       pCapabilities->minCodedExtent.height = ANV_MB_HEIGHT;
282 
283       strcpy(pCapabilities->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_EXTENSION_NAME);
284       pCapabilities->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_SPEC_VERSION;
285       break;
286    }
287    case VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR: {
288       struct VkVideoEncodeH265CapabilitiesKHR *ext = (struct VkVideoEncodeH265CapabilitiesKHR *)
289          vk_find_struct(pCapabilities->pNext, VIDEO_ENCODE_H265_CAPABILITIES_KHR);
290 
291       if (ext) {
292          ext->flags = 0;
293          ext->maxLevelIdc = STD_VIDEO_H265_LEVEL_IDC_5_1;
294          ext->ctbSizes = VK_VIDEO_ENCODE_H265_CTB_SIZE_64_BIT_KHR;
295          ext->transformBlockSizes = VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_4_BIT_KHR |
296                                     VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_8_BIT_KHR |
297                                     VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_16_BIT_KHR |
298                                     VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_32_BIT_KHR;
299          ext->maxPPictureL0ReferenceCount = 8;
300          ext->maxBPictureL0ReferenceCount = 8;
301          ext->maxL1ReferenceCount = 1;
302          ext->minQp = 10;
303          ext->maxQp = 51;
304          ext->maxSliceSegmentCount = 128;
305          ext->maxTiles.width = 1;
306          ext->maxTiles.height = 1;
307          ext->maxSubLayerCount = 1;
308          ext->expectDyadicTemporalSubLayerPattern = false;
309          ext->prefersGopRemainingFrames = 0;
310          ext->requiresGopRemainingFrames = 0;
311       }
312 
313       pCapabilities->minBitstreamBufferOffsetAlignment = 4096;
314       pCapabilities->minBitstreamBufferSizeAlignment = 4096;
315 
316       pCapabilities->maxDpbSlots = ANV_VIDEO_H265_MAX_NUM_REF_FRAME;
317       pCapabilities->maxActiveReferencePictures = ANV_VIDEO_H265_MAX_NUM_REF_FRAME;
318       pCapabilities->pictureAccessGranularity.width = ANV_MAX_H265_CTB_SIZE;
319       pCapabilities->pictureAccessGranularity.height = ANV_MAX_H265_CTB_SIZE;
320       pCapabilities->minCodedExtent.width = ANV_MAX_H265_CTB_SIZE;
321       pCapabilities->minCodedExtent.height = ANV_MAX_H265_CTB_SIZE;
322 
323       strcpy(pCapabilities->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_EXTENSION_NAME);
324       pCapabilities->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_SPEC_VERSION;
325       break;
326    }
327    default:
328       break;
329    }
330 
331    return VK_SUCCESS;
332 }
333 
334 VkResult
anv_GetPhysicalDeviceVideoFormatPropertiesKHR(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceVideoFormatInfoKHR * pVideoFormatInfo,uint32_t * pVideoFormatPropertyCount,VkVideoFormatPropertiesKHR * pVideoFormatProperties)335 anv_GetPhysicalDeviceVideoFormatPropertiesKHR(VkPhysicalDevice physicalDevice,
336                                                const VkPhysicalDeviceVideoFormatInfoKHR *pVideoFormatInfo,
337                                                uint32_t *pVideoFormatPropertyCount,
338                                                VkVideoFormatPropertiesKHR *pVideoFormatProperties)
339 {
340    VK_OUTARRAY_MAKE_TYPED(VkVideoFormatPropertiesKHR, out,
341                           pVideoFormatProperties,
342                           pVideoFormatPropertyCount);
343 
344    const struct VkVideoProfileListInfoKHR *prof_list = (struct VkVideoProfileListInfoKHR *)
345       vk_find_struct_const(pVideoFormatInfo->pNext, VIDEO_PROFILE_LIST_INFO_KHR);
346 
347    /* We only support VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT with
348     * Y-tiling/Tile4, as supported by the hardware for video decoding.
349     * However, we are unable to determine the tiling without modifiers here.
350     * So just disable them all.
351     */
352    const bool decode_dst = !!(pVideoFormatInfo->imageUsage &
353                               VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR);
354 
355    if (prof_list) {
356       for (unsigned i = 0; i < prof_list->profileCount; i++) {
357          const VkVideoProfileInfoKHR *profile = &prof_list->pProfiles[i];
358 
359          if (profile->lumaBitDepth & VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR ||
360              profile->chromaBitDepth & VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR) {
361             vk_outarray_append_typed(VkVideoFormatPropertiesKHR, &out, p) {
362                p->format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
363                p->imageCreateFlags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
364                p->imageType = VK_IMAGE_TYPE_2D;
365                p->imageTiling = VK_IMAGE_TILING_OPTIMAL;
366                p->imageUsageFlags = pVideoFormatInfo->imageUsage;
367             }
368 
369             if (!decode_dst) {
370                vk_outarray_append_typed(VkVideoFormatPropertiesKHR, &out, p) {
371                   p->format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
372                   p->imageCreateFlags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
373                   p->imageType = VK_IMAGE_TYPE_2D;
374                   p->imageTiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
375                   p->imageUsageFlags = pVideoFormatInfo->imageUsage;
376                }
377             }
378          }
379 
380          if (profile->lumaBitDepth & VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR ||
381              profile->chromaBitDepth & VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR) {
382             vk_outarray_append_typed(VkVideoFormatPropertiesKHR, &out, p) {
383                p->format = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16;
384                p->imageCreateFlags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
385                p->imageType = VK_IMAGE_TYPE_2D;
386                p->imageTiling = VK_IMAGE_TILING_OPTIMAL;
387                p->imageUsageFlags = pVideoFormatInfo->imageUsage;
388             }
389             if (!decode_dst) {
390                vk_outarray_append_typed(VkVideoFormatPropertiesKHR, &out, p) {
391                   p->format = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16;
392                   p->imageCreateFlags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
393                   p->imageType = VK_IMAGE_TYPE_2D;
394                   p->imageTiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
395                   p->imageUsageFlags = pVideoFormatInfo->imageUsage;
396                }
397             }
398          }
399       }
400    }
401 
402    return vk_outarray_status(&out);
403 }
404 
405 static uint64_t
get_h264_video_mem_size(struct anv_video_session * vid,uint32_t mem_idx)406 get_h264_video_mem_size(struct anv_video_session *vid, uint32_t mem_idx)
407 {
408    uint32_t width_in_mb =
409       align(vid->vk.max_coded.width, ANV_MB_WIDTH) / ANV_MB_WIDTH;
410 
411    switch (mem_idx) {
412    case ANV_VID_MEM_H264_INTRA_ROW_STORE:
413       return width_in_mb * 64;
414    case ANV_VID_MEM_H264_DEBLOCK_FILTER_ROW_STORE:
415       return width_in_mb * 64 * 4;
416    case ANV_VID_MEM_H264_BSD_MPC_ROW_SCRATCH:
417       return width_in_mb * 64 * 2;
418    case ANV_VID_MEM_H264_MPR_ROW_SCRATCH:
419       return width_in_mb * 64 * 2;
420    default:
421       unreachable("unknown memory");
422    }
423 }
424 
425 static uint64_t
get_h265_video_mem_size(struct anv_video_session * vid,uint32_t mem_idx)426 get_h265_video_mem_size(struct anv_video_session *vid, uint32_t mem_idx)
427 {
428    uint32_t bit_shift =
429       vid->vk.h265.profile_idc == STD_VIDEO_H265_PROFILE_IDC_MAIN_10 ? 2 : 3;
430 
431    /* TODO. these sizes can be determined dynamically depending on ctb sizes of each slice. */
432    uint32_t width_in_ctb =
433       align(vid->vk.max_coded.width, ANV_MAX_H265_CTB_SIZE) / ANV_MAX_H265_CTB_SIZE;
434    uint32_t height_in_ctb =
435       align(vid->vk.max_coded.height, ANV_MAX_H265_CTB_SIZE) / ANV_MAX_H265_CTB_SIZE;
436    uint64_t size;
437 
438    switch (mem_idx) {
439    case ANV_VID_MEM_H265_DEBLOCK_FILTER_ROW_STORE_LINE:
440    case ANV_VID_MEM_H265_DEBLOCK_FILTER_ROW_STORE_TILE_LINE:
441       size = align(vid->vk.max_coded.width, 32) >> bit_shift;
442       break;
443    case ANV_VID_MEM_H265_DEBLOCK_FILTER_ROW_STORE_TILE_COLUMN:
444       size = align(vid->vk.max_coded.height + 6 * height_in_ctb, 32) >> bit_shift;
445       break;
446    case ANV_VID_MEM_H265_METADATA_LINE:
447       size = (((vid->vk.max_coded.width + 15) >> 4) * 188 + width_in_ctb * 9 + 1023) >> 9;
448       break;
449    case ANV_VID_MEM_H265_METADATA_TILE_LINE:
450       size = (((vid->vk.max_coded.width + 15) >> 4) * 172 + width_in_ctb * 9 + 1023) >> 9;
451       break;
452    case ANV_VID_MEM_H265_METADATA_TILE_COLUMN:
453       size = (((vid->vk.max_coded.height + 15) >> 4) * 176 + height_in_ctb * 89 + 1023) >> 9;
454       break;
455    case ANV_VID_MEM_H265_SAO_LINE:
456       size = align((vid->vk.max_coded.width >> 1) + width_in_ctb * 3, 16) >> bit_shift;
457       break;
458    case ANV_VID_MEM_H265_SAO_TILE_LINE:
459       size = align((vid->vk.max_coded.width >> 1) + width_in_ctb * 6, 16) >> bit_shift;
460       break;
461    case ANV_VID_MEM_H265_SAO_TILE_COLUMN:
462       size = align((vid->vk.max_coded.height >> 1) + height_in_ctb * 6, 16) >> bit_shift;
463       break;
464    case ANV_VID_MEM_H265_SSE_SRC_PIX_ROW_STORE: {
465       /* Take the formula from media-driver */
466 #define CACHELINE_SIZE 64
467 #define HEVC_MIN_TILE_SIZE 128
468       uint32_t max_tile_cols = DIV_ROUND_UP(vid->vk.max_coded.width, HEVC_MIN_TILE_SIZE);
469       size = 2 * ((CACHELINE_SIZE * (4 + 4)) << 1) * (width_in_ctb + 3 * max_tile_cols);
470       return size;
471    }
472    default:
473       unreachable("unknown memory");
474    }
475 
476    return size << 6;
477 }
478 
479 static void
get_h264_video_session_mem_reqs(struct anv_video_session * vid,VkVideoSessionMemoryRequirementsKHR * mem_reqs,uint32_t * pVideoSessionMemoryRequirementsCount,uint32_t memory_types)480 get_h264_video_session_mem_reqs(struct anv_video_session *vid,
481                                 VkVideoSessionMemoryRequirementsKHR *mem_reqs,
482                                 uint32_t *pVideoSessionMemoryRequirementsCount,
483                                 uint32_t memory_types)
484 {
485    VK_OUTARRAY_MAKE_TYPED(VkVideoSessionMemoryRequirementsKHR,
486                           out,
487                           mem_reqs,
488                           pVideoSessionMemoryRequirementsCount);
489 
490    for (unsigned i = 0; i < ANV_VID_MEM_H264_MAX; i++) {
491       uint32_t bind_index = ANV_VID_MEM_H264_INTRA_ROW_STORE + i;
492       uint64_t size = get_h264_video_mem_size(vid, i);
493 
494       vk_outarray_append_typed(VkVideoSessionMemoryRequirementsKHR, &out, p) {
495          p->memoryBindIndex = bind_index;
496          p->memoryRequirements.size = size;
497          p->memoryRequirements.alignment = 4096;
498          p->memoryRequirements.memoryTypeBits = memory_types;
499       }
500    }
501 }
502 
503 static void
get_h265_video_session_mem_reqs(struct anv_video_session * vid,VkVideoSessionMemoryRequirementsKHR * mem_reqs,uint32_t * pVideoSessionMemoryRequirementsCount,uint32_t memory_types)504 get_h265_video_session_mem_reqs(struct anv_video_session *vid,
505                                 VkVideoSessionMemoryRequirementsKHR *mem_reqs,
506                                 uint32_t *pVideoSessionMemoryRequirementsCount,
507                                 uint32_t memory_types)
508 {
509    VK_OUTARRAY_MAKE_TYPED(VkVideoSessionMemoryRequirementsKHR,
510                           out,
511                           mem_reqs,
512                           pVideoSessionMemoryRequirementsCount);
513 
514    uint32_t mem_cnt = (vid->vk.op & VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR) ?
515                        ANV_VID_MEM_H265_DEC_MAX : ANV_VID_MEM_H265_ENC_MAX;
516 
517    for (unsigned i = 0; i < mem_cnt; i++) {
518       uint32_t bind_index =
519          ANV_VID_MEM_H265_DEBLOCK_FILTER_ROW_STORE_LINE + i;
520       uint64_t size = get_h265_video_mem_size(vid, i);
521 
522       vk_outarray_append_typed(VkVideoSessionMemoryRequirementsKHR, &out, p) {
523          p->memoryBindIndex = bind_index;
524          p->memoryRequirements.size = size;
525          p->memoryRequirements.alignment = 4096;
526          p->memoryRequirements.memoryTypeBits = memory_types;
527       }
528    }
529 }
530 
531 static const uint8_t av1_buffer_size[ANV_VID_MEM_AV1_MAX][4] = {
532    { 2 ,   4   ,   2   ,    4 },  /* bsdLineBuf, */
533    { 2 ,   4   ,   2   ,    4 },  /* bsdTileLineBuf, */
534    { 2 ,   4   ,   4   ,    8 },  /* intraPredLine, */
535    { 2 ,   4   ,   4   ,    8 },  /* intraPredTileLine, */
536    { 4 ,   8   ,   4   ,    8 },  /* spatialMvLineBuf, */
537    { 4 ,   8   ,   4   ,    8 },  /* spatialMvTileLineBuf, */
538    { 1 ,   1   ,   1   ,    1 },  /* lrMetaTileCol, */
539    { 7 ,   7   ,   7   ,    7 },  /* lrTileLineY, */
540    { 5 ,   5   ,   5   ,    5 },  /* lrTileLineU, */
541    { 5 ,   5   ,   5   ,    5 },  /* lrTileLineV, */
542    { 9 ,   17  ,   11  ,    21 }, /* deblockLineYBuf, */
543    { 3 ,   4   ,   3   ,    5 },  /* deblockLineUBuf, */
544    { 3 ,   4   ,   3   ,    5 },  /* deblockLineVBuf, */
545    { 9 ,   17  ,   11  ,    21 }, /* deblockTileLineYBuf, */
546    { 3 ,   4   ,   3   ,    5 },  /* deblockTileLineVBuf, */
547    { 3 ,   4   ,   3   ,    5 },  /* deblockTileLineUBuf, */
548    { 8 ,   16  ,   10  ,    20 }, /* deblockTileColYBuf, */
549    { 2 ,   4   ,   3   ,    5 },  /* deblockTileColUBuf, */
550    { 2 ,   4   ,   3   ,    5 },  /* deblockTileColVBuf, */
551    { 8 ,   16  ,   10  ,    20 }, /* cdefLineBuf, */
552    { 8 ,   16  ,   10  ,    20 }, /* cdefTileLineBuf, */
553    { 8 ,   16  ,   10  ,    20 }, /* cdefTileColBuf, */
554    { 1 ,   1   ,   1   ,    1 },  /* cdefMetaTileLine, */
555    { 1 ,   1   ,   1   ,    1 },  /* cdefMetaTileCol, */
556    { 1 ,   1   ,   1   ,    1 },  /* cdefTopLeftCornerBuf, */
557    { 22,   44  ,   29  ,    58 }, /* superResTileColYBuf, */
558    { 8 ,   16  ,   10  ,    20 }, /* superResTileColUBuf, */
559    { 8 ,   16  ,   10  ,    20 }, /* superResTileColVBuf, */
560    { 9 ,   17  ,   11  ,    22 }, /* lrTileColYBuf, */
561    { 5 ,   9   ,   6   ,    12 }, /* lrTileColUBuf, */
562    { 5 ,   9   ,   6   ,    12 }, /* lrTileColVBuf, */
563 };
564 
565 static const uint8_t av1_buffer_size_ext[ANV_VID_MEM_AV1_MAX][4] = {
566    { 0 ,    0    ,    0    ,    0 },  /* bsdLineBuf, */
567    { 0 ,    0    ,    0    ,    0 },  /* bsdTileLineBuf, */
568    { 0 ,    0    ,    0    ,    0 },  /* intraPredLine, */
569    { 0 ,    0    ,    0    ,    0 },  /* intraPredTileLine, */
570    { 0 ,    0    ,    0    ,    0 },  /* spatialMvLineBuf, */
571    { 0 ,    0    ,    0    ,    0 },  /* spatialMvTileLineBuf, */
572    { 1 ,    1    ,    1    ,    1 },  /* lrMetaTileCol, */
573    { 0 ,    0    ,    0    ,    0 },  /* lrTileLineY, */
574    { 0 ,    0    ,    0    ,    0 },  /* lrTileLineU, */
575    { 0 ,    0    ,    0    ,    0 },  /* lrTileLineV, */
576    { 0 ,    0    ,    0    ,    0 },  /* deblockLineYBuf, */
577    { 0 ,    0    ,    0    ,    0 },  /* deblockLineUBuf, */
578    { 0 ,    0    ,    0    ,    0 },  /* deblockLineVBuf, */
579    { 0 ,    0    ,    0    ,    0 },  /* deblockTileLineYBuf, */
580    { 0 ,    0    ,    0    ,    0 },  /* deblockTileLineVBuf, */
581    { 0 ,    0    ,    0    ,    0 },  /* deblockTileLineUBuf, */
582    { 0 ,    0    ,    0    ,    0 },  /* deblockTileColYBuf, */
583    { 0 ,    0    ,    0    ,    0 },  /* deblockTileColUBuf, */
584    { 0 ,    0    ,    0    ,    0 },  /* deblockTileColVBuf, */
585    { 1 ,    1    ,    2    ,    2 },  /* cdefLineBuf, */
586    { 1 ,    1    ,    2    ,    2 },  /* cdefTileLineBuf, */
587    { 1 ,    1    ,    2    ,    2 },  /* cdefTileColBuf, */
588    { 0 ,    0    ,    0    ,    0 },  /* cdefMetaTileLine, */
589    { 1 ,    1    ,    1    ,    1 },  /* cdefMetaTileCol, */
590    { 0 ,    0    ,    0    ,    0 },  /* cdefTopLeftCornerBuf, */
591    { 22,    44   ,    29   ,    58 }, /* superResTileColYBuf, */
592    { 8 ,    16   ,    10   ,    20 }, /* superResTileColUBuf, */
593    { 8 ,    16   ,    10   ,    20 }, /* superResTileColVBuf, */
594    { 2 ,    2    ,    2    ,    2 },  /* lrTileColYBuf, */
595    { 1 ,    1    ,    1    ,    1 },  /* lrTileColUBuf, */
596    { 1 ,    1    ,    1    ,    1 },  /* lrTileColVBuf, */
597 };
598 
599 static void
get_av1_video_session_mem_reqs(struct anv_video_session * vid,VkVideoSessionMemoryRequirementsKHR * mem_reqs,uint32_t * pVideoSessionMemoryRequirementsCount,uint32_t memory_types)600 get_av1_video_session_mem_reqs(struct anv_video_session *vid,
601                                VkVideoSessionMemoryRequirementsKHR *mem_reqs,
602                                uint32_t *pVideoSessionMemoryRequirementsCount,
603                                uint32_t memory_types)
604 {
605    VK_OUTARRAY_MAKE_TYPED(VkVideoSessionMemoryRequirementsKHR,
606                           out,
607                           mem_reqs,
608                           pVideoSessionMemoryRequirementsCount);
609    const uint32_t av1_mi_size_log2         = 2;
610    const uint32_t av1_max_mib_size_log2    = 5;
611    uint32_t width = vid->vk.max_coded.width;
612    uint32_t height = vid->vk.max_coded.height;
613    uint32_t mi_cols = width  >> av1_mi_size_log2;
614    uint32_t mi_rows = height >> av1_mi_size_log2;
615    uint32_t width_in_sb = align(mi_cols, (1 << av1_mi_size_log2)) >> av1_mi_size_log2;
616    uint32_t height_in_sb = align(mi_rows, (1 << av1_mi_size_log2)) >> av1_mi_size_log2;
617    uint32_t max_tile_width_sb = DIV_ROUND_UP(4096, 1 << (av1_max_mib_size_log2 + av1_mi_size_log2));
618    uint32_t max_tile_cols = 16; /* TODO. get the profile to work this out */
619 
620    /* Assume 8-bit 128x128 sb is true, can't know at this point */
621    int buf_size_idx = 1;
622 
623    for (enum anv_vid_mem_av1_types mem = ANV_VID_MEM_AV1_BITSTREAM_LINE_ROWSTORE;
624         mem < ANV_VID_MEM_AV1_MAX; mem++) {
625       VkDeviceSize buffer_size = 0;
626 
627       switch (mem) {
628       case ANV_VID_MEM_AV1_BITSTREAM_LINE_ROWSTORE:
629       case ANV_VID_MEM_AV1_INTRA_PREDICTION_LINE_ROWSTORE:
630       case ANV_VID_MEM_AV1_SPATIAL_MOTION_VECTOR_LINE:
631       case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_LINE_Y:
632       case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_LINE_U:
633       case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_LINE_V:
634          buffer_size = max_tile_width_sb * av1_buffer_size[mem][buf_size_idx];
635          break;
636       case ANV_VID_MEM_AV1_CDEF_FILTER_LINE:
637          buffer_size = max_tile_width_sb * av1_buffer_size[mem][buf_size_idx] +
638             av1_buffer_size_ext[mem][buf_size_idx];
639          break;
640       case ANV_VID_MEM_AV1_BITSTREAM_TILE_LINE_ROWSTORE:
641       case ANV_VID_MEM_AV1_SPATIAL_MOTION_VECTOR_TILE_LINE:
642       case ANV_VID_MEM_AV1_INTRA_PREDICTION_TILE_LINE_ROWSTORE:
643       case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_LINE_Y:
644       case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_LINE_U:
645       case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_LINE_V:
646          buffer_size = width_in_sb * av1_buffer_size[mem][buf_size_idx];
647          break;
648 
649       case ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_LINE_Y:
650          buffer_size = max_tile_cols * 7;
651          break;
652       case ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_LINE_U:
653       case ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_LINE_V:
654          buffer_size = max_tile_cols * 5;
655          break;
656 
657       case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_COLUMN_Y:
658       case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_COLUMN_U:
659       case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_COLUMN_V:
660          buffer_size = height_in_sb * av1_buffer_size[mem][buf_size_idx];
661          break;
662       case ANV_VID_MEM_AV1_CDEF_FILTER_TILE_LINE:
663          buffer_size = width_in_sb * av1_buffer_size[mem][buf_size_idx] +
664             av1_buffer_size_ext[mem][buf_size_idx];
665          break;
666       case ANV_VID_MEM_AV1_CDEF_FILTER_META_TILE_LINE:
667          buffer_size = max_tile_cols;
668          break;
669       case ANV_VID_MEM_AV1_CDEF_FILTER_TOP_LEFT_CORNER:
670          buffer_size = max_tile_cols * 8; /* TODO. take from profile */
671          break;
672       case ANV_VID_MEM_AV1_CDEF_FILTER_TILE_COLUMN:
673       case ANV_VID_MEM_AV1_CDEF_FILTER_META_TILE_COLUMN:
674       case ANV_VID_MEM_AV1_SUPER_RES_TILE_COLUMN_Y:
675       case ANV_VID_MEM_AV1_SUPER_RES_TILE_COLUMN_U:
676       case ANV_VID_MEM_AV1_SUPER_RES_TILE_COLUMN_V:
677       case ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_COLUMN_Y:
678       case ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_COLUMN_U:
679       case ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_COLUMN_V:
680       case ANV_VID_MEM_AV1_LOOP_RESTORATION_META_TILE_COLUMN:
681          buffer_size = height_in_sb * av1_buffer_size[mem][buf_size_idx] +
682             av1_buffer_size_ext[mem][buf_size_idx];
683          break;
684       case ANV_VID_MEM_AV1_CDF_DEFAULTS_0:
685       case ANV_VID_MEM_AV1_CDF_DEFAULTS_1:
686       case ANV_VID_MEM_AV1_CDF_DEFAULTS_2:
687       case ANV_VID_MEM_AV1_CDF_DEFAULTS_3:
688          buffer_size = av1_cdf_max_num_bytes;
689          break;
690       case ANV_VID_MEM_AV1_DBD_BUFFER:
691          buffer_size = 1;
692          break;
693       default:
694          assert(0);
695          break;
696       }
697 
698       switch (mem) {
699       case ANV_VID_MEM_AV1_CDF_DEFAULTS_0:
700       case ANV_VID_MEM_AV1_CDF_DEFAULTS_1:
701       case ANV_VID_MEM_AV1_CDF_DEFAULTS_2:
702       case ANV_VID_MEM_AV1_CDF_DEFAULTS_3:
703          break;
704       default:
705          buffer_size *= 64;
706          break;
707       }
708       vk_outarray_append_typed(VkVideoSessionMemoryRequirementsKHR, &out, p) {
709          p->memoryBindIndex = mem;
710          p->memoryRequirements.size = buffer_size;
711          p->memoryRequirements.alignment = 4096;
712          p->memoryRequirements.memoryTypeBits = memory_types;
713       }
714    }
715 }
716 
717 VkResult
anv_GetVideoSessionMemoryRequirementsKHR(VkDevice _device,VkVideoSessionKHR videoSession,uint32_t * pVideoSessionMemoryRequirementsCount,VkVideoSessionMemoryRequirementsKHR * mem_reqs)718 anv_GetVideoSessionMemoryRequirementsKHR(VkDevice _device,
719                                          VkVideoSessionKHR videoSession,
720                                          uint32_t *pVideoSessionMemoryRequirementsCount,
721                                          VkVideoSessionMemoryRequirementsKHR *mem_reqs)
722 {
723    ANV_FROM_HANDLE(anv_device, device, _device);
724    ANV_FROM_HANDLE(anv_video_session, vid, videoSession);
725 
726    uint32_t memory_types =
727       (vid->vk.flags & VK_VIDEO_SESSION_CREATE_PROTECTED_CONTENT_BIT_KHR) ?
728       device->physical->memory.protected_mem_types :
729       device->physical->memory.default_buffer_mem_types;
730    switch (vid->vk.op) {
731    case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR:
732       get_h264_video_session_mem_reqs(vid,
733                                       mem_reqs,
734                                       pVideoSessionMemoryRequirementsCount,
735                                       memory_types);
736       break;
737    case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR:
738       get_h265_video_session_mem_reqs(vid,
739                                       mem_reqs,
740                                       pVideoSessionMemoryRequirementsCount,
741                                       memory_types);
742       break;
743    case VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR:
744       get_h264_video_session_mem_reqs(vid,
745                                       mem_reqs,
746                                       pVideoSessionMemoryRequirementsCount,
747                                       memory_types);
748       break;
749    case VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR:
750       get_h265_video_session_mem_reqs(vid,
751                                       mem_reqs,
752                                       pVideoSessionMemoryRequirementsCount,
753                                       memory_types);
754       break;
755    case VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR:
756       get_av1_video_session_mem_reqs(vid,
757                                      mem_reqs,
758                                      pVideoSessionMemoryRequirementsCount,
759                                      memory_types);
760       break;
761    default:
762       unreachable("unknown codec");
763    }
764 
765    return VK_SUCCESS;
766 }
767 
768 VkResult
anv_UpdateVideoSessionParametersKHR(VkDevice _device,VkVideoSessionParametersKHR _params,const VkVideoSessionParametersUpdateInfoKHR * pUpdateInfo)769 anv_UpdateVideoSessionParametersKHR(VkDevice _device,
770                                      VkVideoSessionParametersKHR _params,
771                                      const VkVideoSessionParametersUpdateInfoKHR *pUpdateInfo)
772 {
773    ANV_FROM_HANDLE(anv_video_session_params, params, _params);
774    return vk_video_session_parameters_update(&params->vk, pUpdateInfo);
775 }
776 
777 static void
copy_bind(struct anv_vid_mem * dst,const VkBindVideoSessionMemoryInfoKHR * src)778 copy_bind(struct anv_vid_mem *dst,
779           const VkBindVideoSessionMemoryInfoKHR *src)
780 {
781    dst->mem = anv_device_memory_from_handle(src->memory);
782    dst->offset = src->memoryOffset;
783    dst->size = src->memorySize;
784 }
785 
786 VkResult
anv_BindVideoSessionMemoryKHR(VkDevice _device,VkVideoSessionKHR videoSession,uint32_t bind_mem_count,const VkBindVideoSessionMemoryInfoKHR * bind_mem)787 anv_BindVideoSessionMemoryKHR(VkDevice _device,
788                               VkVideoSessionKHR videoSession,
789                               uint32_t bind_mem_count,
790                               const VkBindVideoSessionMemoryInfoKHR *bind_mem)
791 {
792    ANV_FROM_HANDLE(anv_video_session, vid, videoSession);
793 
794    switch (vid->vk.op) {
795    case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR:
796    case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR:
797    case VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR:
798       for (unsigned i = 0; i < bind_mem_count; i++) {
799          copy_bind(&vid->vid_mem[bind_mem[i].memoryBindIndex], &bind_mem[i]);
800       }
801       break;
802    case VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR:
803    case VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR:
804       for (unsigned i = 0; i < bind_mem_count; i++) {
805          copy_bind(&vid->vid_mem[bind_mem[i].memoryBindIndex], &bind_mem[i]);
806       }
807       break;
808    default:
809       unreachable("unknown codec");
810    }
811    return VK_SUCCESS;
812 }
813 
814 VKAPI_ATTR VkResult VKAPI_CALL
anv_GetEncodedVideoSessionParametersKHR(VkDevice device,const VkVideoEncodeSessionParametersGetInfoKHR * pVideoSessionParametersInfo,VkVideoEncodeSessionParametersFeedbackInfoKHR * pFeedbackInfo,size_t * pDataSize,void * pData)815 anv_GetEncodedVideoSessionParametersKHR(VkDevice device,
816                                         const VkVideoEncodeSessionParametersGetInfoKHR* pVideoSessionParametersInfo,
817                                         VkVideoEncodeSessionParametersFeedbackInfoKHR* pFeedbackInfo,
818                                         size_t *pDataSize,
819                                         void *pData)
820 {
821    ANV_FROM_HANDLE(anv_video_session_params, params, pVideoSessionParametersInfo->videoSessionParameters);
822    size_t total_size = 0;
823    size_t size_limit = 0;
824 
825    if (pData)
826       size_limit = *pDataSize;
827 
828    switch (params->vk.op) {
829    case VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR: {
830       const struct VkVideoEncodeH264SessionParametersGetInfoKHR *h264_get_info =
831          vk_find_struct_const(pVideoSessionParametersInfo->pNext, VIDEO_ENCODE_H264_SESSION_PARAMETERS_GET_INFO_KHR);
832       size_t sps_size = 0, pps_size = 0;
833       if (h264_get_info->writeStdSPS) {
834          for (unsigned i = 0; i < params->vk.h264_enc.h264_sps_count; i++)
835             if (params->vk.h264_enc.h264_sps[i].base.seq_parameter_set_id == h264_get_info->stdSPSId)
836                vk_video_encode_h264_sps(&params->vk.h264_enc.h264_sps[i].base, size_limit, &sps_size, pData);
837       }
838       if (h264_get_info->writeStdPPS) {
839          char *data_ptr = pData ? (char *)pData + sps_size : NULL;
840          for (unsigned i = 0; i < params->vk.h264_enc.h264_pps_count; i++)
841             if (params->vk.h264_enc.h264_pps[i].base.pic_parameter_set_id == h264_get_info->stdPPSId) {
842                vk_video_encode_h264_pps(&params->vk.h264_enc.h264_pps[i].base, false, size_limit, &pps_size, data_ptr);
843             }
844       }
845       total_size = sps_size + pps_size;
846       break;
847    }
848    case VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR: {
849       const struct VkVideoEncodeH265SessionParametersGetInfoKHR *h265_get_info =
850          vk_find_struct_const(pVideoSessionParametersInfo->pNext, VIDEO_ENCODE_H265_SESSION_PARAMETERS_GET_INFO_KHR);
851       size_t sps_size = 0, pps_size = 0, vps_size = 0;
852       if (h265_get_info->writeStdVPS) {
853          for (unsigned i = 0; i < params->vk.h265_enc.h265_vps_count; i++)
854             if (params->vk.h265_enc.h265_vps[i].base.vps_video_parameter_set_id == h265_get_info->stdVPSId)
855                vk_video_encode_h265_vps(&params->vk.h265_enc.h265_vps[i].base, size_limit, &vps_size, pData);
856       }
857       if (h265_get_info->writeStdSPS) {
858          char *data_ptr = pData ? (char *)pData + vps_size : NULL;
859          for (unsigned i = 0; i < params->vk.h265_enc.h265_sps_count; i++)
860             if (params->vk.h265_enc.h265_sps[i].base.sps_seq_parameter_set_id == h265_get_info->stdSPSId) {
861                vk_video_encode_h265_sps(&params->vk.h265_enc.h265_sps[i].base, size_limit, &sps_size, data_ptr);
862             }
863       }
864       if (h265_get_info->writeStdPPS) {
865          char *data_ptr = pData ? (char *)pData + vps_size + sps_size : NULL;
866          for (unsigned i = 0; i < params->vk.h265_enc.h265_pps_count; i++)
867             if (params->vk.h265_enc.h265_pps[i].base.pps_seq_parameter_set_id == h265_get_info->stdPPSId) {
868                params->vk.h265_enc.h265_pps[i].base.flags.cu_qp_delta_enabled_flag = 0;
869                vk_video_encode_h265_pps(&params->vk.h265_enc.h265_pps[i].base, size_limit, &pps_size, data_ptr);
870             }
871       }
872       total_size = sps_size + pps_size + vps_size;
873       break;
874    }
875    default:
876       break;
877    }
878 
879    /* vk_video_encode_h26x functions support to be safe even if size_limit is not enough,
880     * so we could just confirm whether pDataSize is valid afterwards.
881     */
882    if (pData && *pDataSize < total_size) {
883       *pDataSize = 0;
884       return VK_INCOMPLETE;
885    }
886 
887    *pDataSize = total_size;
888    return VK_SUCCESS;
889 }
890 
891 VkResult
anv_GetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceVideoEncodeQualityLevelInfoKHR * pQualityLevelInfo,VkVideoEncodeQualityLevelPropertiesKHR * pQualityLevelProperties)892 anv_GetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR(VkPhysicalDevice physicalDevice,
893                                                           const VkPhysicalDeviceVideoEncodeQualityLevelInfoKHR* pQualityLevelInfo,
894                                                           VkVideoEncodeQualityLevelPropertiesKHR* pQualityLevelProperties)
895 {
896    /* TODO. */
897    return VK_SUCCESS;
898 }
899 
900 static void
init_single_av1_entry(const struct syntax_element_cdf_table_layout * entry,uint16_t * dst_ptr)901 init_single_av1_entry(const struct syntax_element_cdf_table_layout *entry, uint16_t *dst_ptr)
902 {
903    uint16_t entry_count_per_cl = entry->entry_count_per_cl;
904    uint16_t entry_count_total = entry->entry_count_total;
905    uint16_t start_cl = entry->start_cl;
906 
907    const uint16_t *src = entry->init_data;
908    uint16_t *dst = dst_ptr + start_cl * 32;
909    uint16_t entry_count_left = entry_count_total;
910 
911    while (entry_count_left >= entry_count_per_cl) {
912       memcpy(dst, src, entry_count_per_cl * sizeof(uint16_t));
913       entry_count_left -= entry_count_per_cl;
914 
915       src += entry_count_per_cl;
916       dst += 32;
917    }
918 
919    if (entry_count_left > 0)
920       memcpy(dst, src, entry_count_left * sizeof(uint16_t));
921 }
922 
923 #define INIT_TABLE(x) do {\
924    for (unsigned i = 0; i < ARRAY_SIZE((x)); i++) \
925       init_single_av1_entry(&(x)[i], dst_ptr); \
926    } while (0)
927 
928 static void
init_all_av1_entry(uint16_t * dst_ptr,int index)929 init_all_av1_entry(uint16_t *dst_ptr, int index)
930 {
931    INIT_TABLE(av1_cdf_intra_part1);
932 
933    switch (index) {
934    case 0:
935       INIT_TABLE(av1_cdf_intra_coeffs_0);
936       break;
937    case 1:
938       INIT_TABLE(av1_cdf_intra_coeffs_1);
939       break;
940    case 2:
941       INIT_TABLE(av1_cdf_intra_coeffs_2);
942       break;
943    case 3:
944       INIT_TABLE(av1_cdf_intra_coeffs_3);
945       break;
946    default:
947       unreachable("illegal av1 entry\n");
948    }
949    INIT_TABLE(av1_cdf_intra_part2);
950    INIT_TABLE(av1_cdf_inter);
951 }
952 
953 void
anv_init_av1_cdf_tables(struct anv_cmd_buffer * cmd,struct anv_video_session * vid)954 anv_init_av1_cdf_tables(struct anv_cmd_buffer *cmd,
955                         struct anv_video_session *vid)
956 {
957    void *ptr;
958 
959    for (unsigned i = 0; i < 4; i++) {
960       VkResult result =
961          anv_device_map_bo(cmd->device,
962                            vid->vid_mem[ANV_VID_MEM_AV1_CDF_DEFAULTS_0 + i].mem->bo,
963                            vid->vid_mem[ANV_VID_MEM_AV1_CDF_DEFAULTS_0 + i].offset,
964                            vid->vid_mem[ANV_VID_MEM_AV1_CDF_DEFAULTS_0 + i].size,
965                            NULL,
966                            &ptr);
967 
968       if (result != VK_SUCCESS) {
969          anv_batch_set_error(&cmd->batch, result);
970          return;
971       }
972 
973       init_all_av1_entry(ptr, i);
974       anv_device_unmap_bo(cmd->device, vid->vid_mem[ANV_VID_MEM_AV1_CDF_DEFAULTS_0 + i].mem->bo, ptr,
975                           vid->vid_mem[ANV_VID_MEM_AV1_CDF_DEFAULTS_0 + i].size, NULL);
976 
977    }
978 }
979 
980 uint32_t
anv_video_get_image_mv_size(struct anv_device * device,struct anv_image * image,const struct VkVideoProfileListInfoKHR * profile_list)981 anv_video_get_image_mv_size(struct anv_device *device,
982                             struct anv_image *image,
983                             const struct VkVideoProfileListInfoKHR *profile_list)
984 {
985    uint32_t size = 0;
986 
987    for (unsigned i = 0; i < profile_list->profileCount; i++) {
988       if (profile_list->pProfiles[i].videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR) {
989          unsigned w_mb = DIV_ROUND_UP(image->vk.extent.width, ANV_MB_WIDTH);
990          unsigned h_mb = DIV_ROUND_UP(image->vk.extent.height, ANV_MB_HEIGHT);
991          size = w_mb * h_mb * 128;
992       } else if (profile_list->pProfiles[i].videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR) {
993          unsigned w_mb = DIV_ROUND_UP(image->vk.extent.width, 32);
994          unsigned h_mb = DIV_ROUND_UP(image->vk.extent.height, 32);
995          size = ALIGN(w_mb * h_mb, 2) << 6;
996       } else if (profile_list->pProfiles[i].videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) {
997          const uint32_t av1_mi_size_log2 = 2;
998          uint32_t width = image->vk.extent.width;
999          uint32_t height = image->vk.extent.height;
1000          uint32_t mi_cols = width  >> av1_mi_size_log2;
1001          uint32_t mi_rows = height >> av1_mi_size_log2;
1002          uint32_t width_in_sb = align(mi_cols, (1 << av1_mi_size_log2)) >> av1_mi_size_log2;
1003          uint32_t height_in_sb = align(mi_rows, (1 << av1_mi_size_log2)) >> av1_mi_size_log2;
1004          uint32_t sb_total = width_in_sb * height_in_sb;
1005 
1006          size = sb_total * 16;
1007       }
1008    }
1009    return size;
1010 }
1011