uvd_enc_tests.c revision 00a23bda
1/* 2 * Copyright 2017 Advanced Micro Devices, Inc. 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 shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22*/ 23 24#ifdef HAVE_CONFIG_H 25#include "config.h" 26#endif 27 28#include <stdio.h> 29#include <inttypes.h> 30 31#include "CUnit/Basic.h" 32 33#include "util_math.h" 34 35#include "amdgpu_test.h" 36#include "amdgpu_drm.h" 37#include "amdgpu_internal.h" 38#include "frame.h" 39#include "uve_ib.h" 40 41#define IB_SIZE 4096 42#define MAX_RESOURCES 16 43 44struct amdgpu_uvd_enc_bo { 45 amdgpu_bo_handle handle; 46 amdgpu_va_handle va_handle; 47 uint64_t addr; 48 uint64_t size; 49 uint8_t *ptr; 50}; 51 52struct amdgpu_uvd_enc { 53 unsigned width; 54 unsigned height; 55 struct amdgpu_uvd_enc_bo session; 56 struct amdgpu_uvd_enc_bo vbuf; 57 struct amdgpu_uvd_enc_bo bs; 58 struct amdgpu_uvd_enc_bo fb; 59 struct amdgpu_uvd_enc_bo cpb; 60}; 61 62static amdgpu_device_handle device_handle; 63static uint32_t major_version; 64static uint32_t minor_version; 65static uint32_t family_id; 66 67static amdgpu_context_handle context_handle; 68static amdgpu_bo_handle ib_handle; 69static amdgpu_va_handle ib_va_handle; 70static uint64_t ib_mc_address; 71static uint32_t *ib_cpu; 72 73static struct amdgpu_uvd_enc enc; 74static amdgpu_bo_handle resources[MAX_RESOURCES]; 75static unsigned num_resources; 76 77static void amdgpu_cs_uvd_enc_create(void); 78static void amdgpu_cs_uvd_enc_session_init(void); 79static void amdgpu_cs_uvd_enc_encode(void); 80static void amdgpu_cs_uvd_enc_destroy(void); 81 82 83CU_TestInfo uvd_enc_tests[] = { 84 { "UVD ENC create", amdgpu_cs_uvd_enc_create }, 85 { "UVD ENC session init", amdgpu_cs_uvd_enc_session_init }, 86 { "UVD ENC encode", amdgpu_cs_uvd_enc_encode }, 87 { "UVD ENC destroy", amdgpu_cs_uvd_enc_destroy }, 88 CU_TEST_INFO_NULL, 89}; 90 91CU_BOOL suite_uvd_enc_tests_enable(void) 92{ 93 int r; 94 struct drm_amdgpu_info_hw_ip info; 95 96 if (amdgpu_device_initialize(drm_amdgpu[0], &major_version, 97 &minor_version, &device_handle)) 98 return CU_FALSE; 99 100 r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_UVD_ENC, 0, &info); 101 102 if (amdgpu_device_deinitialize(device_handle)) 103 return CU_FALSE; 104 105 if (!info.available_rings) 106 printf("\n\nThe ASIC NOT support UVD ENC, suite disabled.\n"); 107 108 return (r == 0 && (info.available_rings ? CU_TRUE : CU_FALSE)); 109} 110 111 112int suite_uvd_enc_tests_init(void) 113{ 114 int r; 115 116 r = amdgpu_device_initialize(drm_amdgpu[0], &major_version, 117 &minor_version, &device_handle); 118 if (r) 119 return CUE_SINIT_FAILED; 120 121 family_id = device_handle->info.family_id; 122 123 r = amdgpu_cs_ctx_create(device_handle, &context_handle); 124 if (r) 125 return CUE_SINIT_FAILED; 126 127 r = amdgpu_bo_alloc_and_map(device_handle, IB_SIZE, 4096, 128 AMDGPU_GEM_DOMAIN_GTT, 0, 129 &ib_handle, (void**)&ib_cpu, 130 &ib_mc_address, &ib_va_handle); 131 if (r) 132 return CUE_SINIT_FAILED; 133 134 return CUE_SUCCESS; 135} 136 137int suite_uvd_enc_tests_clean(void) 138{ 139 int r; 140 141 r = amdgpu_bo_unmap_and_free(ib_handle, ib_va_handle, 142 ib_mc_address, IB_SIZE); 143 if (r) 144 return CUE_SCLEAN_FAILED; 145 146 r = amdgpu_cs_ctx_free(context_handle); 147 if (r) 148 return CUE_SCLEAN_FAILED; 149 150 r = amdgpu_device_deinitialize(device_handle); 151 if (r) 152 return CUE_SCLEAN_FAILED; 153 154 return CUE_SUCCESS; 155} 156 157static int submit(unsigned ndw, unsigned ip) 158{ 159 struct amdgpu_cs_request ibs_request = {0}; 160 struct amdgpu_cs_ib_info ib_info = {0}; 161 struct amdgpu_cs_fence fence_status = {0}; 162 uint32_t expired; 163 int r; 164 165 ib_info.ib_mc_address = ib_mc_address; 166 ib_info.size = ndw; 167 168 ibs_request.ip_type = ip; 169 170 r = amdgpu_bo_list_create(device_handle, num_resources, resources, 171 NULL, &ibs_request.resources); 172 if (r) 173 return r; 174 175 ibs_request.number_of_ibs = 1; 176 ibs_request.ibs = &ib_info; 177 ibs_request.fence_info.handle = NULL; 178 179 r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1); 180 if (r) 181 return r; 182 183 r = amdgpu_bo_list_destroy(ibs_request.resources); 184 if (r) 185 return r; 186 187 fence_status.context = context_handle; 188 fence_status.ip_type = ip; 189 fence_status.fence = ibs_request.seq_no; 190 191 r = amdgpu_cs_query_fence_status(&fence_status, 192 AMDGPU_TIMEOUT_INFINITE, 193 0, &expired); 194 if (r) 195 return r; 196 197 return 0; 198} 199 200static void alloc_resource(struct amdgpu_uvd_enc_bo *uvd_enc_bo, 201 unsigned size, unsigned domain) 202{ 203 struct amdgpu_bo_alloc_request req = {0}; 204 amdgpu_bo_handle buf_handle; 205 amdgpu_va_handle va_handle; 206 uint64_t va = 0; 207 int r; 208 209 req.alloc_size = ALIGN(size, 4096); 210 req.preferred_heap = domain; 211 r = amdgpu_bo_alloc(device_handle, &req, &buf_handle); 212 CU_ASSERT_EQUAL(r, 0); 213 r = amdgpu_va_range_alloc(device_handle, 214 amdgpu_gpu_va_range_general, 215 req.alloc_size, 1, 0, &va, 216 &va_handle, 0); 217 CU_ASSERT_EQUAL(r, 0); 218 r = amdgpu_bo_va_op(buf_handle, 0, req.alloc_size, va, 0, 219 AMDGPU_VA_OP_MAP); 220 CU_ASSERT_EQUAL(r, 0); 221 uvd_enc_bo->addr = va; 222 uvd_enc_bo->handle = buf_handle; 223 uvd_enc_bo->size = req.alloc_size; 224 uvd_enc_bo->va_handle = va_handle; 225 r = amdgpu_bo_cpu_map(uvd_enc_bo->handle, (void **)&uvd_enc_bo->ptr); 226 CU_ASSERT_EQUAL(r, 0); 227 memset(uvd_enc_bo->ptr, 0, size); 228 r = amdgpu_bo_cpu_unmap(uvd_enc_bo->handle); 229 CU_ASSERT_EQUAL(r, 0); 230} 231 232static void free_resource(struct amdgpu_uvd_enc_bo *uvd_enc_bo) 233{ 234 int r; 235 236 r = amdgpu_bo_va_op(uvd_enc_bo->handle, 0, uvd_enc_bo->size, 237 uvd_enc_bo->addr, 0, AMDGPU_VA_OP_UNMAP); 238 CU_ASSERT_EQUAL(r, 0); 239 240 r = amdgpu_va_range_free(uvd_enc_bo->va_handle); 241 CU_ASSERT_EQUAL(r, 0); 242 243 r = amdgpu_bo_free(uvd_enc_bo->handle); 244 CU_ASSERT_EQUAL(r, 0); 245 memset(uvd_enc_bo, 0, sizeof(*uvd_enc_bo)); 246} 247 248static void amdgpu_cs_uvd_enc_create(void) 249{ 250 enc.width = 160; 251 enc.height = 128; 252 253 num_resources = 0; 254 alloc_resource(&enc.session, 128 * 1024, AMDGPU_GEM_DOMAIN_GTT); 255 resources[num_resources++] = enc.session.handle; 256 resources[num_resources++] = ib_handle; 257} 258 259static void check_result(struct amdgpu_uvd_enc *enc) 260{ 261 uint64_t sum; 262 uint32_t s = 175602; 263 uint32_t *ptr, size; 264 int j, r; 265 266 r = amdgpu_bo_cpu_map(enc->fb.handle, (void **)&enc->fb.ptr); 267 CU_ASSERT_EQUAL(r, 0); 268 ptr = (uint32_t *)enc->fb.ptr; 269 size = ptr[6]; 270 r = amdgpu_bo_cpu_unmap(enc->fb.handle); 271 CU_ASSERT_EQUAL(r, 0); 272 r = amdgpu_bo_cpu_map(enc->bs.handle, (void **)&enc->bs.ptr); 273 CU_ASSERT_EQUAL(r, 0); 274 for (j = 0, sum = 0; j < size; ++j) 275 sum += enc->bs.ptr[j]; 276 CU_ASSERT_EQUAL(sum, s); 277 r = amdgpu_bo_cpu_unmap(enc->bs.handle); 278 CU_ASSERT_EQUAL(r, 0); 279 280} 281 282static void amdgpu_cs_uvd_enc_session_init(void) 283{ 284 int len, r; 285 286 len = 0; 287 memcpy((ib_cpu + len), uve_session_info, sizeof(uve_session_info)); 288 len += sizeof(uve_session_info) / 4; 289 ib_cpu[len++] = enc.session.addr >> 32; 290 ib_cpu[len++] = enc.session.addr; 291 292 memcpy((ib_cpu + len), uve_task_info, sizeof(uve_task_info)); 293 len += sizeof(uve_task_info) / 4; 294 ib_cpu[len++] = 0x000000d8; 295 ib_cpu[len++] = 0x00000000; 296 ib_cpu[len++] = 0x00000000; 297 298 memcpy((ib_cpu + len), uve_op_init, sizeof(uve_op_init)); 299 len += sizeof(uve_op_init) / 4; 300 301 memcpy((ib_cpu + len), uve_session_init, sizeof(uve_session_init)); 302 len += sizeof(uve_session_init) / 4; 303 304 memcpy((ib_cpu + len), uve_layer_ctrl, sizeof(uve_layer_ctrl)); 305 len += sizeof(uve_layer_ctrl) / 4; 306 307 memcpy((ib_cpu + len), uve_slice_ctrl, sizeof(uve_slice_ctrl)); 308 len += sizeof(uve_slice_ctrl) / 4; 309 310 memcpy((ib_cpu + len), uve_spec_misc, sizeof(uve_spec_misc)); 311 len += sizeof(uve_spec_misc) / 4; 312 313 memcpy((ib_cpu + len), uve_rc_session_init, sizeof(uve_rc_session_init)); 314 len += sizeof(uve_rc_session_init) / 4; 315 316 memcpy((ib_cpu + len), uve_deblocking_filter, sizeof(uve_deblocking_filter)); 317 len += sizeof(uve_deblocking_filter) / 4; 318 319 memcpy((ib_cpu + len), uve_quality_params, sizeof(uve_quality_params)); 320 len += sizeof(uve_quality_params) / 4; 321 322 memcpy((ib_cpu + len), uve_op_init_rc, sizeof(uve_op_init_rc)); 323 len += sizeof(uve_op_init_rc) / 4; 324 325 memcpy((ib_cpu + len), uve_op_init_rc_vbv_level, sizeof(uve_op_init_rc_vbv_level)); 326 len += sizeof(uve_op_init_rc_vbv_level) / 4; 327 328 r = submit(len, AMDGPU_HW_IP_UVD_ENC); 329 CU_ASSERT_EQUAL(r, 0); 330} 331 332static void amdgpu_cs_uvd_enc_encode(void) 333{ 334 int len, r, i; 335 uint64_t luma_offset, chroma_offset; 336 uint32_t vbuf_size, bs_size = 0x003f4800, cpb_size; 337 unsigned align = (family_id >= AMDGPU_FAMILY_AI) ? 256 : 16; 338 vbuf_size = ALIGN(enc.width, align) * ALIGN(enc.height, 16) * 1.5; 339 cpb_size = vbuf_size * 10; 340 341 342 num_resources = 0; 343 alloc_resource(&enc.fb, 4096, AMDGPU_GEM_DOMAIN_VRAM); 344 resources[num_resources++] = enc.fb.handle; 345 alloc_resource(&enc.bs, bs_size, AMDGPU_GEM_DOMAIN_VRAM); 346 resources[num_resources++] = enc.bs.handle; 347 alloc_resource(&enc.vbuf, vbuf_size, AMDGPU_GEM_DOMAIN_VRAM); 348 resources[num_resources++] = enc.vbuf.handle; 349 alloc_resource(&enc.cpb, cpb_size, AMDGPU_GEM_DOMAIN_VRAM); 350 resources[num_resources++] = enc.cpb.handle; 351 resources[num_resources++] = ib_handle; 352 353 r = amdgpu_bo_cpu_map(enc.vbuf.handle, (void **)&enc.vbuf.ptr); 354 CU_ASSERT_EQUAL(r, 0); 355 356 memset(enc.vbuf.ptr, 0, vbuf_size); 357 for (i = 0; i < enc.height; ++i) { 358 memcpy(enc.vbuf.ptr, (frame + i * enc.width), enc.width); 359 enc.vbuf.ptr += ALIGN(enc.width, align); 360 } 361 for (i = 0; i < enc.height / 2; ++i) { 362 memcpy(enc.vbuf.ptr, ((frame + enc.height * enc.width) + i * enc.width), enc.width); 363 enc.vbuf.ptr += ALIGN(enc.width, align); 364 } 365 366 r = amdgpu_bo_cpu_unmap(enc.vbuf.handle); 367 CU_ASSERT_EQUAL(r, 0); 368 369 len = 0; 370 memcpy((ib_cpu + len), uve_session_info, sizeof(uve_session_info)); 371 len += sizeof(uve_session_info) / 4; 372 ib_cpu[len++] = enc.session.addr >> 32; 373 ib_cpu[len++] = enc.session.addr; 374 375 memcpy((ib_cpu + len), uve_task_info, sizeof(uve_task_info)); 376 len += sizeof(uve_task_info) / 4; 377 ib_cpu[len++] = 0x000005e0; 378 ib_cpu[len++] = 0x00000001; 379 ib_cpu[len++] = 0x00000001; 380 381 memcpy((ib_cpu + len), uve_nalu_buffer_1, sizeof(uve_nalu_buffer_1)); 382 len += sizeof(uve_nalu_buffer_1) / 4; 383 384 memcpy((ib_cpu + len), uve_nalu_buffer_2, sizeof(uve_nalu_buffer_2)); 385 len += sizeof(uve_nalu_buffer_2) / 4; 386 387 memcpy((ib_cpu + len), uve_nalu_buffer_3, sizeof(uve_nalu_buffer_3)); 388 len += sizeof(uve_nalu_buffer_3) / 4; 389 390 memcpy((ib_cpu + len), uve_nalu_buffer_4, sizeof(uve_nalu_buffer_4)); 391 len += sizeof(uve_nalu_buffer_4) / 4; 392 393 memcpy((ib_cpu + len), uve_slice_header, sizeof(uve_slice_header)); 394 len += sizeof(uve_slice_header) / 4; 395 396 ib_cpu[len++] = 0x00000254; 397 ib_cpu[len++] = 0x00000010; 398 ib_cpu[len++] = enc.cpb.addr >> 32; 399 ib_cpu[len++] = enc.cpb.addr; 400 memcpy((ib_cpu + len), uve_ctx_buffer, sizeof(uve_ctx_buffer)); 401 len += sizeof(uve_ctx_buffer) / 4; 402 403 memcpy((ib_cpu + len), uve_bitstream_buffer, sizeof(uve_bitstream_buffer)); 404 len += sizeof(uve_bitstream_buffer) / 4; 405 ib_cpu[len++] = 0x00000000; 406 ib_cpu[len++] = enc.bs.addr >> 32; 407 ib_cpu[len++] = enc.bs.addr; 408 ib_cpu[len++] = 0x003f4800; 409 ib_cpu[len++] = 0x00000000; 410 411 memcpy((ib_cpu + len), uve_feedback_buffer, sizeof(uve_feedback_buffer)); 412 len += sizeof(uve_feedback_buffer) / 4; 413 ib_cpu[len++] = enc.fb.addr >> 32; 414 ib_cpu[len++] = enc.fb.addr; 415 ib_cpu[len++] = 0x00000010; 416 ib_cpu[len++] = 0x00000028; 417 418 memcpy((ib_cpu + len), uve_feedback_buffer_additional, sizeof(uve_feedback_buffer_additional)); 419 len += sizeof(uve_feedback_buffer_additional) / 4; 420 421 memcpy((ib_cpu + len), uve_intra_refresh, sizeof(uve_intra_refresh)); 422 len += sizeof(uve_intra_refresh) / 4; 423 424 memcpy((ib_cpu + len), uve_layer_select, sizeof(uve_layer_select)); 425 len += sizeof(uve_layer_select) / 4; 426 427 memcpy((ib_cpu + len), uve_rc_layer_init, sizeof(uve_rc_layer_init)); 428 len += sizeof(uve_rc_layer_init) / 4; 429 430 memcpy((ib_cpu + len), uve_layer_select, sizeof(uve_layer_select)); 431 len += sizeof(uve_layer_select) / 4; 432 433 memcpy((ib_cpu + len), uve_rc_per_pic, sizeof(uve_rc_per_pic)); 434 len += sizeof(uve_rc_per_pic) / 4; 435 436 unsigned luma_size = ALIGN(enc.width, align) * ALIGN(enc.height, 16); 437 luma_offset = enc.vbuf.addr; 438 chroma_offset = luma_offset + luma_size; 439 ib_cpu[len++] = 0x00000054; 440 ib_cpu[len++] = 0x0000000c; 441 ib_cpu[len++] = 0x00000002; 442 ib_cpu[len++] = 0x003f4800; 443 ib_cpu[len++] = luma_offset >> 32; 444 ib_cpu[len++] = luma_offset; 445 ib_cpu[len++] = chroma_offset >> 32; 446 ib_cpu[len++] = chroma_offset; 447 memcpy((ib_cpu + len), uve_encode_param, sizeof(uve_encode_param)); 448 ib_cpu[len] = ALIGN(enc.width, align); 449 ib_cpu[len + 1] = ALIGN(enc.width, align); 450 len += sizeof(uve_encode_param) / 4; 451 452 memcpy((ib_cpu + len), uve_op_speed_enc_mode, sizeof(uve_op_speed_enc_mode)); 453 len += sizeof(uve_op_speed_enc_mode) / 4; 454 455 memcpy((ib_cpu + len), uve_op_encode, sizeof(uve_op_encode)); 456 len += sizeof(uve_op_encode) / 4; 457 458 r = submit(len, AMDGPU_HW_IP_UVD_ENC); 459 CU_ASSERT_EQUAL(r, 0); 460 461 check_result(&enc); 462 463 free_resource(&enc.fb); 464 free_resource(&enc.bs); 465 free_resource(&enc.vbuf); 466 free_resource(&enc.cpb); 467} 468 469static void amdgpu_cs_uvd_enc_destroy(void) 470{ 471 int len, r; 472 473 num_resources = 0; 474 resources[num_resources++] = ib_handle; 475 476 len = 0; 477 memcpy((ib_cpu + len), uve_session_info, sizeof(uve_session_info)); 478 len += sizeof(uve_session_info) / 4; 479 ib_cpu[len++] = enc.session.addr >> 32; 480 ib_cpu[len++] = enc.session.addr; 481 482 memcpy((ib_cpu + len), uve_task_info, sizeof(uve_task_info)); 483 len += sizeof(uve_task_info) / 4; 484 ib_cpu[len++] = 0xffffffff; 485 ib_cpu[len++] = 0x00000002; 486 ib_cpu[len++] = 0x00000000; 487 488 memcpy((ib_cpu + len), uve_op_close, sizeof(uve_op_close)); 489 len += sizeof(uve_op_close) / 4; 490 491 r = submit(len, AMDGPU_HW_IP_UVD_ENC); 492 CU_ASSERT_EQUAL(r, 0); 493 494 free_resource(&enc.session); 495} 496