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 ¶ms->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, ¶ms->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(¶ms->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(¶ms->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(¶ms->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(¶ms->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(¶ms->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(¶ms->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