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 if (prof_list) {
348 for (unsigned i = 0; i < prof_list->profileCount; i++) {
349 const VkVideoProfileInfoKHR *profile = &prof_list->pProfiles[i];
350
351 if (profile->lumaBitDepth & VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR ||
352 profile->chromaBitDepth & VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR) {
353 vk_outarray_append_typed(VkVideoFormatPropertiesKHR, &out, p) {
354 p->format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
355 p->imageCreateFlags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
356 p->imageType = VK_IMAGE_TYPE_2D;
357 p->imageTiling = VK_IMAGE_TILING_OPTIMAL;
358 p->imageUsageFlags = pVideoFormatInfo->imageUsage;
359 }
360
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_DRM_FORMAT_MODIFIER_EXT;
366 p->imageUsageFlags = pVideoFormatInfo->imageUsage;
367 }
368 }
369
370 if (profile->lumaBitDepth & VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR ||
371 profile->chromaBitDepth & VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR) {
372 vk_outarray_append_typed(VkVideoFormatPropertiesKHR, &out, p) {
373 p->format = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16;
374 p->imageCreateFlags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
375 p->imageType = VK_IMAGE_TYPE_2D;
376 p->imageTiling = VK_IMAGE_TILING_OPTIMAL;
377 p->imageUsageFlags = pVideoFormatInfo->imageUsage;
378 }
379 vk_outarray_append_typed(VkVideoFormatPropertiesKHR, &out, p) {
380 p->format = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16;
381 p->imageCreateFlags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
382 p->imageType = VK_IMAGE_TYPE_2D;
383 p->imageTiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
384 p->imageUsageFlags = pVideoFormatInfo->imageUsage;
385 }
386 }
387 }
388 }
389
390 return vk_outarray_status(&out);
391 }
392
393 static uint64_t
get_h264_video_mem_size(struct anv_video_session * vid,uint32_t mem_idx)394 get_h264_video_mem_size(struct anv_video_session *vid, uint32_t mem_idx)
395 {
396 uint32_t width_in_mb =
397 align(vid->vk.max_coded.width, ANV_MB_WIDTH) / ANV_MB_WIDTH;
398
399 switch (mem_idx) {
400 case ANV_VID_MEM_H264_INTRA_ROW_STORE:
401 return width_in_mb * 64;
402 case ANV_VID_MEM_H264_DEBLOCK_FILTER_ROW_STORE:
403 return width_in_mb * 64 * 4;
404 case ANV_VID_MEM_H264_BSD_MPC_ROW_SCRATCH:
405 return width_in_mb * 64 * 2;
406 case ANV_VID_MEM_H264_MPR_ROW_SCRATCH:
407 return width_in_mb * 64 * 2;
408 default:
409 unreachable("unknown memory");
410 }
411 }
412
413 static uint64_t
get_h265_video_mem_size(struct anv_video_session * vid,uint32_t mem_idx)414 get_h265_video_mem_size(struct anv_video_session *vid, uint32_t mem_idx)
415 {
416 uint32_t bit_shift =
417 vid->vk.h265.profile_idc == STD_VIDEO_H265_PROFILE_IDC_MAIN_10 ? 2 : 3;
418
419 /* TODO. these sizes can be determined dynamically depending on ctb sizes of each slice. */
420 uint32_t width_in_ctb =
421 align(vid->vk.max_coded.width, ANV_MAX_H265_CTB_SIZE) / ANV_MAX_H265_CTB_SIZE;
422 uint32_t height_in_ctb =
423 align(vid->vk.max_coded.height, ANV_MAX_H265_CTB_SIZE) / ANV_MAX_H265_CTB_SIZE;
424 uint64_t size;
425
426 switch (mem_idx) {
427 case ANV_VID_MEM_H265_DEBLOCK_FILTER_ROW_STORE_LINE:
428 case ANV_VID_MEM_H265_DEBLOCK_FILTER_ROW_STORE_TILE_LINE:
429 size = align(vid->vk.max_coded.width, 32) >> bit_shift;
430 break;
431 case ANV_VID_MEM_H265_DEBLOCK_FILTER_ROW_STORE_TILE_COLUMN:
432 size = align(vid->vk.max_coded.height + 6 * height_in_ctb, 32) >> bit_shift;
433 break;
434 case ANV_VID_MEM_H265_METADATA_LINE:
435 size = (((vid->vk.max_coded.width + 15) >> 4) * 188 + width_in_ctb * 9 + 1023) >> 9;
436 break;
437 case ANV_VID_MEM_H265_METADATA_TILE_LINE:
438 size = (((vid->vk.max_coded.width + 15) >> 4) * 172 + width_in_ctb * 9 + 1023) >> 9;
439 break;
440 case ANV_VID_MEM_H265_METADATA_TILE_COLUMN:
441 size = (((vid->vk.max_coded.height + 15) >> 4) * 176 + height_in_ctb * 89 + 1023) >> 9;
442 break;
443 case ANV_VID_MEM_H265_SAO_LINE:
444 size = align((vid->vk.max_coded.width >> 1) + width_in_ctb * 3, 16) >> bit_shift;
445 break;
446 case ANV_VID_MEM_H265_SAO_TILE_LINE:
447 size = align((vid->vk.max_coded.width >> 1) + width_in_ctb * 6, 16) >> bit_shift;
448 break;
449 case ANV_VID_MEM_H265_SAO_TILE_COLUMN:
450 size = align((vid->vk.max_coded.height >> 1) + height_in_ctb * 6, 16) >> bit_shift;
451 break;
452 case ANV_VID_MEM_H265_SSE_SRC_PIX_ROW_STORE: {
453 /* Take the formula from media-driver */
454 #define CACHELINE_SIZE 64
455 #define HEVC_MIN_TILE_SIZE 128
456 uint32_t max_tile_cols = DIV_ROUND_UP(vid->vk.max_coded.width, HEVC_MIN_TILE_SIZE);
457 size = 2 * ((CACHELINE_SIZE * (4 + 4)) << 1) * (width_in_ctb + 3 * max_tile_cols);
458 return size;
459 }
460 default:
461 unreachable("unknown memory");
462 }
463
464 return size << 6;
465 }
466
467 static void
get_h264_video_session_mem_reqs(struct anv_video_session * vid,VkVideoSessionMemoryRequirementsKHR * mem_reqs,uint32_t * pVideoSessionMemoryRequirementsCount,uint32_t memory_types)468 get_h264_video_session_mem_reqs(struct anv_video_session *vid,
469 VkVideoSessionMemoryRequirementsKHR *mem_reqs,
470 uint32_t *pVideoSessionMemoryRequirementsCount,
471 uint32_t memory_types)
472 {
473 VK_OUTARRAY_MAKE_TYPED(VkVideoSessionMemoryRequirementsKHR,
474 out,
475 mem_reqs,
476 pVideoSessionMemoryRequirementsCount);
477
478 for (unsigned i = 0; i < ANV_VID_MEM_H264_MAX; i++) {
479 uint32_t bind_index = ANV_VID_MEM_H264_INTRA_ROW_STORE + i;
480 uint64_t size = get_h264_video_mem_size(vid, i);
481
482 vk_outarray_append_typed(VkVideoSessionMemoryRequirementsKHR, &out, p) {
483 p->memoryBindIndex = bind_index;
484 p->memoryRequirements.size = size;
485 p->memoryRequirements.alignment = 4096;
486 p->memoryRequirements.memoryTypeBits = memory_types;
487 }
488 }
489 }
490
491 static void
get_h265_video_session_mem_reqs(struct anv_video_session * vid,VkVideoSessionMemoryRequirementsKHR * mem_reqs,uint32_t * pVideoSessionMemoryRequirementsCount,uint32_t memory_types)492 get_h265_video_session_mem_reqs(struct anv_video_session *vid,
493 VkVideoSessionMemoryRequirementsKHR *mem_reqs,
494 uint32_t *pVideoSessionMemoryRequirementsCount,
495 uint32_t memory_types)
496 {
497 VK_OUTARRAY_MAKE_TYPED(VkVideoSessionMemoryRequirementsKHR,
498 out,
499 mem_reqs,
500 pVideoSessionMemoryRequirementsCount);
501
502 uint32_t mem_cnt = (vid->vk.op & VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR) ?
503 ANV_VID_MEM_H265_DEC_MAX : ANV_VID_MEM_H265_ENC_MAX;
504
505 for (unsigned i = 0; i < mem_cnt; i++) {
506 uint32_t bind_index =
507 ANV_VID_MEM_H265_DEBLOCK_FILTER_ROW_STORE_LINE + i;
508 uint64_t size = get_h265_video_mem_size(vid, i);
509
510 vk_outarray_append_typed(VkVideoSessionMemoryRequirementsKHR, &out, p) {
511 p->memoryBindIndex = bind_index;
512 p->memoryRequirements.size = size;
513 p->memoryRequirements.alignment = 4096;
514 p->memoryRequirements.memoryTypeBits = memory_types;
515 }
516 }
517 }
518
519 static const uint8_t av1_buffer_size[ANV_VID_MEM_AV1_MAX][4] = {
520 { 2 , 4 , 2 , 4 }, /* bsdLineBuf, */
521 { 2 , 4 , 2 , 4 }, /* bsdTileLineBuf, */
522 { 2 , 4 , 4 , 8 }, /* intraPredLine, */
523 { 2 , 4 , 4 , 8 }, /* intraPredTileLine, */
524 { 4 , 8 , 4 , 8 }, /* spatialMvLineBuf, */
525 { 4 , 8 , 4 , 8 }, /* spatialMvTileLineBuf, */
526 { 1 , 1 , 1 , 1 }, /* lrMetaTileCol, */
527 { 7 , 7 , 7 , 7 }, /* lrTileLineY, */
528 { 5 , 5 , 5 , 5 }, /* lrTileLineU, */
529 { 5 , 5 , 5 , 5 }, /* lrTileLineV, */
530 { 9 , 17 , 11 , 21 }, /* deblockLineYBuf, */
531 { 3 , 4 , 3 , 5 }, /* deblockLineUBuf, */
532 { 3 , 4 , 3 , 5 }, /* deblockLineVBuf, */
533 { 9 , 17 , 11 , 21 }, /* deblockTileLineYBuf, */
534 { 3 , 4 , 3 , 5 }, /* deblockTileLineVBuf, */
535 { 3 , 4 , 3 , 5 }, /* deblockTileLineUBuf, */
536 { 8 , 16 , 10 , 20 }, /* deblockTileColYBuf, */
537 { 2 , 4 , 3 , 5 }, /* deblockTileColUBuf, */
538 { 2 , 4 , 3 , 5 }, /* deblockTileColVBuf, */
539 { 8 , 16 , 10 , 20 }, /* cdefLineBuf, */
540 { 8 , 16 , 10 , 20 }, /* cdefTileLineBuf, */
541 { 8 , 16 , 10 , 20 }, /* cdefTileColBuf, */
542 { 1 , 1 , 1 , 1 }, /* cdefMetaTileLine, */
543 { 1 , 1 , 1 , 1 }, /* cdefMetaTileCol, */
544 { 1 , 1 , 1 , 1 }, /* cdefTopLeftCornerBuf, */
545 { 22, 44 , 29 , 58 }, /* superResTileColYBuf, */
546 { 8 , 16 , 10 , 20 }, /* superResTileColUBuf, */
547 { 8 , 16 , 10 , 20 }, /* superResTileColVBuf, */
548 { 9 , 17 , 11 , 22 }, /* lrTileColYBuf, */
549 { 5 , 9 , 6 , 12 }, /* lrTileColUBuf, */
550 { 5 , 9 , 6 , 12 }, /* lrTileColVBuf, */
551 };
552
553 static const uint8_t av1_buffer_size_ext[ANV_VID_MEM_AV1_MAX][4] = {
554 { 0 , 0 , 0 , 0 }, /* bsdLineBuf, */
555 { 0 , 0 , 0 , 0 }, /* bsdTileLineBuf, */
556 { 0 , 0 , 0 , 0 }, /* intraPredLine, */
557 { 0 , 0 , 0 , 0 }, /* intraPredTileLine, */
558 { 0 , 0 , 0 , 0 }, /* spatialMvLineBuf, */
559 { 0 , 0 , 0 , 0 }, /* spatialMvTileLineBuf, */
560 { 1 , 1 , 1 , 1 }, /* lrMetaTileCol, */
561 { 0 , 0 , 0 , 0 }, /* lrTileLineY, */
562 { 0 , 0 , 0 , 0 }, /* lrTileLineU, */
563 { 0 , 0 , 0 , 0 }, /* lrTileLineV, */
564 { 0 , 0 , 0 , 0 }, /* deblockLineYBuf, */
565 { 0 , 0 , 0 , 0 }, /* deblockLineUBuf, */
566 { 0 , 0 , 0 , 0 }, /* deblockLineVBuf, */
567 { 0 , 0 , 0 , 0 }, /* deblockTileLineYBuf, */
568 { 0 , 0 , 0 , 0 }, /* deblockTileLineVBuf, */
569 { 0 , 0 , 0 , 0 }, /* deblockTileLineUBuf, */
570 { 0 , 0 , 0 , 0 }, /* deblockTileColYBuf, */
571 { 0 , 0 , 0 , 0 }, /* deblockTileColUBuf, */
572 { 0 , 0 , 0 , 0 }, /* deblockTileColVBuf, */
573 { 1 , 1 , 2 , 2 }, /* cdefLineBuf, */
574 { 1 , 1 , 2 , 2 }, /* cdefTileLineBuf, */
575 { 1 , 1 , 2 , 2 }, /* cdefTileColBuf, */
576 { 0 , 0 , 0 , 0 }, /* cdefMetaTileLine, */
577 { 1 , 1 , 1 , 1 }, /* cdefMetaTileCol, */
578 { 0 , 0 , 0 , 0 }, /* cdefTopLeftCornerBuf, */
579 { 22, 44 , 29 , 58 }, /* superResTileColYBuf, */
580 { 8 , 16 , 10 , 20 }, /* superResTileColUBuf, */
581 { 8 , 16 , 10 , 20 }, /* superResTileColVBuf, */
582 { 2 , 2 , 2 , 2 }, /* lrTileColYBuf, */
583 { 1 , 1 , 1 , 1 }, /* lrTileColUBuf, */
584 { 1 , 1 , 1 , 1 }, /* lrTileColVBuf, */
585 };
586
587 static void
get_av1_video_session_mem_reqs(struct anv_video_session * vid,VkVideoSessionMemoryRequirementsKHR * mem_reqs,uint32_t * pVideoSessionMemoryRequirementsCount,uint32_t memory_types)588 get_av1_video_session_mem_reqs(struct anv_video_session *vid,
589 VkVideoSessionMemoryRequirementsKHR *mem_reqs,
590 uint32_t *pVideoSessionMemoryRequirementsCount,
591 uint32_t memory_types)
592 {
593 VK_OUTARRAY_MAKE_TYPED(VkVideoSessionMemoryRequirementsKHR,
594 out,
595 mem_reqs,
596 pVideoSessionMemoryRequirementsCount);
597 const uint32_t av1_mi_size_log2 = 2;
598 const uint32_t av1_max_mib_size_log2 = 5;
599 uint32_t width = vid->vk.max_coded.width;
600 uint32_t height = vid->vk.max_coded.height;
601 uint32_t mi_cols = width >> av1_mi_size_log2;
602 uint32_t mi_rows = height >> av1_mi_size_log2;
603 uint32_t width_in_sb = align(mi_cols, (1 << av1_mi_size_log2)) >> av1_mi_size_log2;
604 uint32_t height_in_sb = align(mi_rows, (1 << av1_mi_size_log2)) >> av1_mi_size_log2;
605 uint32_t max_tile_width_sb = DIV_ROUND_UP(4096, 1 << (av1_max_mib_size_log2 + av1_mi_size_log2));
606 uint32_t max_tile_cols = 16; /* TODO. get the profile to work this out */
607
608 /* Assume 8-bit 128x128 sb is true, can't know at this point */
609 int buf_size_idx = 1;
610
611 for (enum anv_vid_mem_av1_types mem = ANV_VID_MEM_AV1_BITSTREAM_LINE_ROWSTORE;
612 mem < ANV_VID_MEM_AV1_MAX; mem++) {
613 VkDeviceSize buffer_size = 0;
614
615 switch (mem) {
616 case ANV_VID_MEM_AV1_BITSTREAM_LINE_ROWSTORE:
617 case ANV_VID_MEM_AV1_INTRA_PREDICTION_LINE_ROWSTORE:
618 case ANV_VID_MEM_AV1_SPATIAL_MOTION_VECTOR_LINE:
619 case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_LINE_Y:
620 case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_LINE_U:
621 case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_LINE_V:
622 buffer_size = max_tile_width_sb * av1_buffer_size[mem][buf_size_idx];
623 break;
624 case ANV_VID_MEM_AV1_CDEF_FILTER_LINE:
625 buffer_size = max_tile_width_sb * av1_buffer_size[mem][buf_size_idx] +
626 av1_buffer_size_ext[mem][buf_size_idx];
627 break;
628 case ANV_VID_MEM_AV1_BITSTREAM_TILE_LINE_ROWSTORE:
629 case ANV_VID_MEM_AV1_SPATIAL_MOTION_VECTOR_TILE_LINE:
630 case ANV_VID_MEM_AV1_INTRA_PREDICTION_TILE_LINE_ROWSTORE:
631 case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_LINE_Y:
632 case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_LINE_U:
633 case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_LINE_V:
634 buffer_size = width_in_sb * av1_buffer_size[mem][buf_size_idx];
635 break;
636
637 case ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_LINE_Y:
638 buffer_size = max_tile_cols * 7;
639 break;
640 case ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_LINE_U:
641 case ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_LINE_V:
642 buffer_size = max_tile_cols * 5;
643 break;
644
645 case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_COLUMN_Y:
646 case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_COLUMN_U:
647 case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_COLUMN_V:
648 buffer_size = height_in_sb * av1_buffer_size[mem][buf_size_idx];
649 break;
650 case ANV_VID_MEM_AV1_CDEF_FILTER_TILE_LINE:
651 buffer_size = width_in_sb * av1_buffer_size[mem][buf_size_idx] +
652 av1_buffer_size_ext[mem][buf_size_idx];
653 break;
654 case ANV_VID_MEM_AV1_CDEF_FILTER_META_TILE_LINE:
655 buffer_size = max_tile_cols;
656 break;
657 case ANV_VID_MEM_AV1_CDEF_FILTER_TOP_LEFT_CORNER:
658 buffer_size = max_tile_cols * 8; /* TODO. take from profile */
659 break;
660 case ANV_VID_MEM_AV1_CDEF_FILTER_TILE_COLUMN:
661 case ANV_VID_MEM_AV1_CDEF_FILTER_META_TILE_COLUMN:
662 case ANV_VID_MEM_AV1_SUPER_RES_TILE_COLUMN_Y:
663 case ANV_VID_MEM_AV1_SUPER_RES_TILE_COLUMN_U:
664 case ANV_VID_MEM_AV1_SUPER_RES_TILE_COLUMN_V:
665 case ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_COLUMN_Y:
666 case ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_COLUMN_U:
667 case ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_COLUMN_V:
668 case ANV_VID_MEM_AV1_LOOP_RESTORATION_META_TILE_COLUMN:
669 buffer_size = height_in_sb * av1_buffer_size[mem][buf_size_idx] +
670 av1_buffer_size_ext[mem][buf_size_idx];
671 break;
672 case ANV_VID_MEM_AV1_CDF_DEFAULTS_0:
673 case ANV_VID_MEM_AV1_CDF_DEFAULTS_1:
674 case ANV_VID_MEM_AV1_CDF_DEFAULTS_2:
675 case ANV_VID_MEM_AV1_CDF_DEFAULTS_3:
676 buffer_size = av1_cdf_max_num_bytes;
677 break;
678 case ANV_VID_MEM_AV1_DBD_BUFFER:
679 buffer_size = 1;
680 break;
681 default:
682 assert(0);
683 break;
684 }
685
686 switch (mem) {
687 case ANV_VID_MEM_AV1_CDF_DEFAULTS_0:
688 case ANV_VID_MEM_AV1_CDF_DEFAULTS_1:
689 case ANV_VID_MEM_AV1_CDF_DEFAULTS_2:
690 case ANV_VID_MEM_AV1_CDF_DEFAULTS_3:
691 break;
692 default:
693 buffer_size *= 64;
694 break;
695 }
696 vk_outarray_append_typed(VkVideoSessionMemoryRequirementsKHR, &out, p) {
697 p->memoryBindIndex = mem;
698 p->memoryRequirements.size = buffer_size;
699 p->memoryRequirements.alignment = 4096;
700 p->memoryRequirements.memoryTypeBits = memory_types;
701 }
702 }
703 }
704
705 VkResult
anv_GetVideoSessionMemoryRequirementsKHR(VkDevice _device,VkVideoSessionKHR videoSession,uint32_t * pVideoSessionMemoryRequirementsCount,VkVideoSessionMemoryRequirementsKHR * mem_reqs)706 anv_GetVideoSessionMemoryRequirementsKHR(VkDevice _device,
707 VkVideoSessionKHR videoSession,
708 uint32_t *pVideoSessionMemoryRequirementsCount,
709 VkVideoSessionMemoryRequirementsKHR *mem_reqs)
710 {
711 ANV_FROM_HANDLE(anv_device, device, _device);
712 ANV_FROM_HANDLE(anv_video_session, vid, videoSession);
713
714 uint32_t memory_types =
715 (vid->vk.flags & VK_VIDEO_SESSION_CREATE_PROTECTED_CONTENT_BIT_KHR) ?
716 device->physical->memory.protected_mem_types :
717 device->physical->memory.default_buffer_mem_types;
718 switch (vid->vk.op) {
719 case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR:
720 get_h264_video_session_mem_reqs(vid,
721 mem_reqs,
722 pVideoSessionMemoryRequirementsCount,
723 memory_types);
724 break;
725 case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR:
726 get_h265_video_session_mem_reqs(vid,
727 mem_reqs,
728 pVideoSessionMemoryRequirementsCount,
729 memory_types);
730 break;
731 case VK_VIDEO_CODEC_OPERATION_ENCODE_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_ENCODE_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_DECODE_AV1_BIT_KHR:
744 get_av1_video_session_mem_reqs(vid,
745 mem_reqs,
746 pVideoSessionMemoryRequirementsCount,
747 memory_types);
748 break;
749 default:
750 unreachable("unknown codec");
751 }
752
753 return VK_SUCCESS;
754 }
755
756 VkResult
anv_UpdateVideoSessionParametersKHR(VkDevice _device,VkVideoSessionParametersKHR _params,const VkVideoSessionParametersUpdateInfoKHR * pUpdateInfo)757 anv_UpdateVideoSessionParametersKHR(VkDevice _device,
758 VkVideoSessionParametersKHR _params,
759 const VkVideoSessionParametersUpdateInfoKHR *pUpdateInfo)
760 {
761 ANV_FROM_HANDLE(anv_video_session_params, params, _params);
762 return vk_video_session_parameters_update(¶ms->vk, pUpdateInfo);
763 }
764
765 static void
copy_bind(struct anv_vid_mem * dst,const VkBindVideoSessionMemoryInfoKHR * src)766 copy_bind(struct anv_vid_mem *dst,
767 const VkBindVideoSessionMemoryInfoKHR *src)
768 {
769 dst->mem = anv_device_memory_from_handle(src->memory);
770 dst->offset = src->memoryOffset;
771 dst->size = src->memorySize;
772 }
773
774 VkResult
anv_BindVideoSessionMemoryKHR(VkDevice _device,VkVideoSessionKHR videoSession,uint32_t bind_mem_count,const VkBindVideoSessionMemoryInfoKHR * bind_mem)775 anv_BindVideoSessionMemoryKHR(VkDevice _device,
776 VkVideoSessionKHR videoSession,
777 uint32_t bind_mem_count,
778 const VkBindVideoSessionMemoryInfoKHR *bind_mem)
779 {
780 ANV_FROM_HANDLE(anv_video_session, vid, videoSession);
781
782 switch (vid->vk.op) {
783 case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR:
784 case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR:
785 case VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR:
786 for (unsigned i = 0; i < bind_mem_count; i++) {
787 copy_bind(&vid->vid_mem[bind_mem[i].memoryBindIndex], &bind_mem[i]);
788 }
789 break;
790 case VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR:
791 case VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR:
792 for (unsigned i = 0; i < bind_mem_count; i++) {
793 copy_bind(&vid->vid_mem[bind_mem[i].memoryBindIndex], &bind_mem[i]);
794 }
795 break;
796 default:
797 unreachable("unknown codec");
798 }
799 return VK_SUCCESS;
800 }
801
802 VKAPI_ATTR VkResult VKAPI_CALL
anv_GetEncodedVideoSessionParametersKHR(VkDevice device,const VkVideoEncodeSessionParametersGetInfoKHR * pVideoSessionParametersInfo,VkVideoEncodeSessionParametersFeedbackInfoKHR * pFeedbackInfo,size_t * pDataSize,void * pData)803 anv_GetEncodedVideoSessionParametersKHR(VkDevice device,
804 const VkVideoEncodeSessionParametersGetInfoKHR* pVideoSessionParametersInfo,
805 VkVideoEncodeSessionParametersFeedbackInfoKHR* pFeedbackInfo,
806 size_t *pDataSize,
807 void *pData)
808 {
809 ANV_FROM_HANDLE(anv_video_session_params, params, pVideoSessionParametersInfo->videoSessionParameters);
810 size_t total_size = 0;
811 size_t size_limit = 0;
812
813 if (pData)
814 size_limit = *pDataSize;
815
816 switch (params->vk.op) {
817 case VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR: {
818 const struct VkVideoEncodeH264SessionParametersGetInfoKHR *h264_get_info =
819 vk_find_struct_const(pVideoSessionParametersInfo->pNext, VIDEO_ENCODE_H264_SESSION_PARAMETERS_GET_INFO_KHR);
820 size_t sps_size = 0, pps_size = 0;
821 if (h264_get_info->writeStdSPS) {
822 for (unsigned i = 0; i < params->vk.h264_enc.h264_sps_count; i++)
823 if (params->vk.h264_enc.h264_sps[i].base.seq_parameter_set_id == h264_get_info->stdSPSId)
824 vk_video_encode_h264_sps(¶ms->vk.h264_enc.h264_sps[i].base, size_limit, &sps_size, pData);
825 }
826 if (h264_get_info->writeStdPPS) {
827 char *data_ptr = pData ? (char *)pData + sps_size : NULL;
828 for (unsigned i = 0; i < params->vk.h264_enc.h264_pps_count; i++)
829 if (params->vk.h264_enc.h264_pps[i].base.pic_parameter_set_id == h264_get_info->stdPPSId) {
830 vk_video_encode_h264_pps(¶ms->vk.h264_enc.h264_pps[i].base, false, size_limit, &pps_size, data_ptr);
831 }
832 }
833 total_size = sps_size + pps_size;
834 break;
835 }
836 case VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR: {
837 const struct VkVideoEncodeH265SessionParametersGetInfoKHR *h265_get_info =
838 vk_find_struct_const(pVideoSessionParametersInfo->pNext, VIDEO_ENCODE_H265_SESSION_PARAMETERS_GET_INFO_KHR);
839 size_t sps_size = 0, pps_size = 0, vps_size = 0;
840 if (h265_get_info->writeStdVPS) {
841 for (unsigned i = 0; i < params->vk.h265_enc.h265_vps_count; i++)
842 if (params->vk.h265_enc.h265_vps[i].base.vps_video_parameter_set_id == h265_get_info->stdVPSId)
843 vk_video_encode_h265_vps(¶ms->vk.h265_enc.h265_vps[i].base, size_limit, &vps_size, pData);
844 }
845 if (h265_get_info->writeStdSPS) {
846 char *data_ptr = pData ? (char *)pData + vps_size : NULL;
847 for (unsigned i = 0; i < params->vk.h265_enc.h265_sps_count; i++)
848 if (params->vk.h265_enc.h265_sps[i].base.sps_seq_parameter_set_id == h265_get_info->stdSPSId) {
849 vk_video_encode_h265_sps(¶ms->vk.h265_enc.h265_sps[i].base, size_limit, &sps_size, data_ptr);
850 }
851 }
852 if (h265_get_info->writeStdPPS) {
853 char *data_ptr = pData ? (char *)pData + vps_size + sps_size : NULL;
854 for (unsigned i = 0; i < params->vk.h265_enc.h265_pps_count; i++)
855 if (params->vk.h265_enc.h265_pps[i].base.pps_seq_parameter_set_id == h265_get_info->stdPPSId) {
856 params->vk.h265_enc.h265_pps[i].base.flags.cu_qp_delta_enabled_flag = 0;
857 vk_video_encode_h265_pps(¶ms->vk.h265_enc.h265_pps[i].base, size_limit, &pps_size, data_ptr);
858 }
859 }
860 total_size = sps_size + pps_size + vps_size;
861 break;
862 }
863 default:
864 break;
865 }
866
867 /* vk_video_encode_h26x functions support to be safe even if size_limit is not enough,
868 * so we could just confirm whether pDataSize is valid afterwards.
869 */
870 if (pData && *pDataSize < total_size) {
871 *pDataSize = 0;
872 return VK_INCOMPLETE;
873 }
874
875 *pDataSize = total_size;
876 return VK_SUCCESS;
877 }
878
879 VkResult
anv_GetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceVideoEncodeQualityLevelInfoKHR * pQualityLevelInfo,VkVideoEncodeQualityLevelPropertiesKHR * pQualityLevelProperties)880 anv_GetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR(VkPhysicalDevice physicalDevice,
881 const VkPhysicalDeviceVideoEncodeQualityLevelInfoKHR* pQualityLevelInfo,
882 VkVideoEncodeQualityLevelPropertiesKHR* pQualityLevelProperties)
883 {
884 /* TODO. */
885 return VK_SUCCESS;
886 }
887
888 static void
init_single_av1_entry(const struct syntax_element_cdf_table_layout * entry,uint16_t * dst_ptr)889 init_single_av1_entry(const struct syntax_element_cdf_table_layout *entry, uint16_t *dst_ptr)
890 {
891 uint16_t entry_count_per_cl = entry->entry_count_per_cl;
892 uint16_t entry_count_total = entry->entry_count_total;
893 uint16_t start_cl = entry->start_cl;
894
895 const uint16_t *src = entry->init_data;
896 uint16_t *dst = dst_ptr + start_cl * 32;
897 uint16_t entry_count_left = entry_count_total;
898
899 while (entry_count_left >= entry_count_per_cl) {
900 memcpy(dst, src, entry_count_per_cl * sizeof(uint16_t));
901 entry_count_left -= entry_count_per_cl;
902
903 src += entry_count_per_cl;
904 dst += 32;
905 }
906
907 if (entry_count_left > 0)
908 memcpy(dst, src, entry_count_left * sizeof(uint16_t));
909 }
910
911 #define INIT_TABLE(x) do {\
912 for (unsigned i = 0; i < ARRAY_SIZE((x)); i++) \
913 init_single_av1_entry(&(x)[i], dst_ptr); \
914 } while (0)
915
916 static void
init_all_av1_entry(uint16_t * dst_ptr,int index)917 init_all_av1_entry(uint16_t *dst_ptr, int index)
918 {
919 INIT_TABLE(av1_cdf_intra_part1);
920
921 switch (index) {
922 case 0:
923 INIT_TABLE(av1_cdf_intra_coeffs_0);
924 break;
925 case 1:
926 INIT_TABLE(av1_cdf_intra_coeffs_1);
927 break;
928 case 2:
929 INIT_TABLE(av1_cdf_intra_coeffs_2);
930 break;
931 case 3:
932 INIT_TABLE(av1_cdf_intra_coeffs_3);
933 break;
934 default:
935 unreachable("illegal av1 entry\n");
936 }
937 INIT_TABLE(av1_cdf_intra_part2);
938 INIT_TABLE(av1_cdf_inter);
939 }
940
941 void
anv_init_av1_cdf_tables(struct anv_cmd_buffer * cmd,struct anv_video_session * vid)942 anv_init_av1_cdf_tables(struct anv_cmd_buffer *cmd,
943 struct anv_video_session *vid)
944 {
945 void *ptr;
946
947 for (unsigned i = 0; i < 4; i++) {
948 VkResult result =
949 anv_device_map_bo(cmd->device,
950 vid->vid_mem[ANV_VID_MEM_AV1_CDF_DEFAULTS_0 + i].mem->bo,
951 vid->vid_mem[ANV_VID_MEM_AV1_CDF_DEFAULTS_0 + i].offset,
952 vid->vid_mem[ANV_VID_MEM_AV1_CDF_DEFAULTS_0 + i].size,
953 NULL,
954 &ptr);
955
956 if (result != VK_SUCCESS) {
957 anv_batch_set_error(&cmd->batch, result);
958 return;
959 }
960
961 init_all_av1_entry(ptr, i);
962 anv_device_unmap_bo(cmd->device, vid->vid_mem[ANV_VID_MEM_AV1_CDF_DEFAULTS_0 + i].mem->bo, ptr,
963 vid->vid_mem[ANV_VID_MEM_AV1_CDF_DEFAULTS_0 + i].size, NULL);
964
965 }
966 }
967
968 uint32_t
anv_video_get_image_mv_size(struct anv_device * device,struct anv_image * image,const struct VkVideoProfileListInfoKHR * profile_list)969 anv_video_get_image_mv_size(struct anv_device *device,
970 struct anv_image *image,
971 const struct VkVideoProfileListInfoKHR *profile_list)
972 {
973 uint32_t size = 0;
974
975 for (unsigned i = 0; i < profile_list->profileCount; i++) {
976 if (profile_list->pProfiles[i].videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR) {
977 unsigned w_mb = DIV_ROUND_UP(image->vk.extent.width, ANV_MB_WIDTH);
978 unsigned h_mb = DIV_ROUND_UP(image->vk.extent.height, ANV_MB_HEIGHT);
979 size = w_mb * h_mb * 128;
980 } else if (profile_list->pProfiles[i].videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR) {
981 unsigned w_mb = DIV_ROUND_UP(image->vk.extent.width, 32);
982 unsigned h_mb = DIV_ROUND_UP(image->vk.extent.height, 32);
983 size = ALIGN(w_mb * h_mb, 2) << 6;
984 } else if (profile_list->pProfiles[i].videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) {
985 const uint32_t av1_mi_size_log2 = 2;
986 uint32_t width = image->vk.extent.width;
987 uint32_t height = image->vk.extent.height;
988 uint32_t mi_cols = width >> av1_mi_size_log2;
989 uint32_t mi_rows = height >> av1_mi_size_log2;
990 uint32_t width_in_sb = align(mi_cols, (1 << av1_mi_size_log2)) >> av1_mi_size_log2;
991 uint32_t height_in_sb = align(mi_rows, (1 << av1_mi_size_log2)) >> av1_mi_size_log2;
992 uint32_t sb_total = width_in_sb * height_in_sb;
993
994 size = sb_total * 16;
995 }
996 }
997 return size;
998 }
999