uvd_enc_tests.c revision d8807b2f
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 82CU_TestInfo uvd_enc_tests[] = { 83 { "UVD ENC create", amdgpu_cs_uvd_enc_create }, 84 { "UVD ENC session init", amdgpu_cs_uvd_enc_session_init }, 85 { "UVD ENC encode", amdgpu_cs_uvd_enc_encode }, 86 { "UVD ENC destroy", amdgpu_cs_uvd_enc_destroy }, 87 CU_TEST_INFO_NULL, 88}; 89 90int suite_uvd_enc_tests_init(void) 91{ 92 int r; 93 94 r = amdgpu_device_initialize(drm_amdgpu[0], &major_version, 95 &minor_version, &device_handle); 96 if (r) 97 return CUE_SINIT_FAILED; 98 99 family_id = device_handle->info.family_id; 100 101 if (family_id < AMDGPU_FAMILY_AI || family_id >= AMDGPU_FAMILY_RV) { 102 printf("\n\nThe ASIC NOT support UVD ENC, all sub-tests will pass\n"); 103 return CUE_SUCCESS; 104 } 105 106 r = amdgpu_cs_ctx_create(device_handle, &context_handle); 107 if (r) 108 return CUE_SINIT_FAILED; 109 110 r = amdgpu_bo_alloc_and_map(device_handle, IB_SIZE, 4096, 111 AMDGPU_GEM_DOMAIN_GTT, 0, 112 &ib_handle, (void**)&ib_cpu, 113 &ib_mc_address, &ib_va_handle); 114 if (r) 115 return CUE_SINIT_FAILED; 116 117 return CUE_SUCCESS; 118} 119 120int suite_uvd_enc_tests_clean(void) 121{ 122 int r; 123 124 if (family_id < AMDGPU_FAMILY_AI || family_id >= AMDGPU_FAMILY_RV) { 125 126 r = amdgpu_device_deinitialize(device_handle); 127 if (r) 128 return CUE_SCLEAN_FAILED; 129 130 return CUE_SUCCESS; 131 } else { 132 133 r = amdgpu_bo_unmap_and_free(ib_handle, ib_va_handle, 134 ib_mc_address, IB_SIZE); 135 if (r) 136 return CUE_SCLEAN_FAILED; 137 138 r = amdgpu_cs_ctx_free(context_handle); 139 if (r) 140 return CUE_SCLEAN_FAILED; 141 142 r = amdgpu_device_deinitialize(device_handle); 143 if (r) 144 return CUE_SCLEAN_FAILED; 145 } 146 147 return CUE_SUCCESS; 148} 149 150static int submit(unsigned ndw, unsigned ip) 151{ 152 struct amdgpu_cs_request ibs_request = {0}; 153 struct amdgpu_cs_ib_info ib_info = {0}; 154 struct amdgpu_cs_fence fence_status = {0}; 155 uint32_t expired; 156 int r; 157 158 ib_info.ib_mc_address = ib_mc_address; 159 ib_info.size = ndw; 160 161 ibs_request.ip_type = ip; 162 163 r = amdgpu_bo_list_create(device_handle, num_resources, resources, 164 NULL, &ibs_request.resources); 165 if (r) 166 return r; 167 168 ibs_request.number_of_ibs = 1; 169 ibs_request.ibs = &ib_info; 170 ibs_request.fence_info.handle = NULL; 171 172 r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1); 173 if (r) 174 return r; 175 176 r = amdgpu_bo_list_destroy(ibs_request.resources); 177 if (r) 178 return r; 179 180 fence_status.context = context_handle; 181 fence_status.ip_type = ip; 182 fence_status.fence = ibs_request.seq_no; 183 184 r = amdgpu_cs_query_fence_status(&fence_status, 185 AMDGPU_TIMEOUT_INFINITE, 186 0, &expired); 187 if (r) 188 return r; 189 190 return 0; 191} 192 193static void alloc_resource(struct amdgpu_uvd_enc_bo *uvd_enc_bo, 194 unsigned size, unsigned domain) 195{ 196 struct amdgpu_bo_alloc_request req = {0}; 197 amdgpu_bo_handle buf_handle; 198 amdgpu_va_handle va_handle; 199 uint64_t va = 0; 200 int r; 201 202 req.alloc_size = ALIGN(size, 4096); 203 req.preferred_heap = domain; 204 r = amdgpu_bo_alloc(device_handle, &req, &buf_handle); 205 CU_ASSERT_EQUAL(r, 0); 206 r = amdgpu_va_range_alloc(device_handle, 207 amdgpu_gpu_va_range_general, 208 req.alloc_size, 1, 0, &va, 209 &va_handle, 0); 210 CU_ASSERT_EQUAL(r, 0); 211 r = amdgpu_bo_va_op(buf_handle, 0, req.alloc_size, va, 0, 212 AMDGPU_VA_OP_MAP); 213 CU_ASSERT_EQUAL(r, 0); 214 uvd_enc_bo->addr = va; 215 uvd_enc_bo->handle = buf_handle; 216 uvd_enc_bo->size = req.alloc_size; 217 uvd_enc_bo->va_handle = va_handle; 218 r = amdgpu_bo_cpu_map(uvd_enc_bo->handle, (void **)&uvd_enc_bo->ptr); 219 CU_ASSERT_EQUAL(r, 0); 220 memset(uvd_enc_bo->ptr, 0, size); 221 r = amdgpu_bo_cpu_unmap(uvd_enc_bo->handle); 222 CU_ASSERT_EQUAL(r, 0); 223} 224 225static void free_resource(struct amdgpu_uvd_enc_bo *uvd_enc_bo) 226{ 227 int r; 228 229 r = amdgpu_bo_va_op(uvd_enc_bo->handle, 0, uvd_enc_bo->size, 230 uvd_enc_bo->addr, 0, AMDGPU_VA_OP_UNMAP); 231 CU_ASSERT_EQUAL(r, 0); 232 233 r = amdgpu_va_range_free(uvd_enc_bo->va_handle); 234 CU_ASSERT_EQUAL(r, 0); 235 236 r = amdgpu_bo_free(uvd_enc_bo->handle); 237 CU_ASSERT_EQUAL(r, 0); 238 memset(uvd_enc_bo, 0, sizeof(*uvd_enc_bo)); 239} 240 241static void amdgpu_cs_uvd_enc_create(void) 242{ 243 int len, r; 244 245 if (family_id < AMDGPU_FAMILY_AI || family_id >= AMDGPU_FAMILY_RV) 246 return; 247 248 enc.width = 160; 249 enc.height = 128; 250 251 num_resources = 0; 252 alloc_resource(&enc.session, 128 * 1024, AMDGPU_GEM_DOMAIN_GTT); 253 resources[num_resources++] = enc.session.handle; 254 resources[num_resources++] = ib_handle; 255} 256 257static void check_result(struct amdgpu_uvd_enc *enc) 258{ 259 uint64_t sum; 260 uint32_t s = 26382; 261 uint32_t *ptr, size; 262 int i, j, r; 263 264 r = amdgpu_bo_cpu_map(enc->fb.handle, (void **)&enc->fb.ptr); 265 CU_ASSERT_EQUAL(r, 0); 266 ptr = (uint32_t *)enc->fb.ptr; 267 size = ptr[6]; 268 r = amdgpu_bo_cpu_unmap(enc->fb.handle); 269 CU_ASSERT_EQUAL(r, 0); 270 r = amdgpu_bo_cpu_map(enc->bs.handle, (void **)&enc->bs.ptr); 271 CU_ASSERT_EQUAL(r, 0); 272 for (j = 0, sum = 0; j < size; ++j) 273 sum += enc->bs.ptr[j]; 274 CU_ASSERT_EQUAL(sum, s); 275 r = amdgpu_bo_cpu_unmap(enc->bs.handle); 276 CU_ASSERT_EQUAL(r, 0); 277 278} 279 280static void amdgpu_cs_uvd_enc_session_init(void) 281{ 282 int len, r; 283 284 if (family_id < AMDGPU_FAMILY_AI || family_id >= AMDGPU_FAMILY_RV) 285 return; 286 287 len = 0; 288 memcpy((ib_cpu + len), uve_session_info, sizeof(uve_session_info)); 289 len += sizeof(uve_session_info) / 4; 290 ib_cpu[len++] = enc.session.addr >> 32; 291 ib_cpu[len++] = enc.session.addr; 292 293 memcpy((ib_cpu + len), uve_task_info, sizeof(uve_task_info)); 294 len += sizeof(uve_task_info) / 4; 295 ib_cpu[len++] = 0x000000d8; 296 ib_cpu[len++] = 0x00000000; 297 ib_cpu[len++] = 0x00000000; 298 299 memcpy((ib_cpu + len), uve_op_init, sizeof(uve_op_init)); 300 len += sizeof(uve_op_init) / 4; 301 302 memcpy((ib_cpu + len), uve_session_init, sizeof(uve_session_init)); 303 len += sizeof(uve_session_init) / 4; 304 305 memcpy((ib_cpu + len), uve_layer_ctrl, sizeof(uve_layer_ctrl)); 306 len += sizeof(uve_layer_ctrl) / 4; 307 308 memcpy((ib_cpu + len), uve_slice_ctrl, sizeof(uve_slice_ctrl)); 309 len += sizeof(uve_slice_ctrl) / 4; 310 311 memcpy((ib_cpu + len), uve_spec_misc, sizeof(uve_spec_misc)); 312 len += sizeof(uve_spec_misc) / 4; 313 314 memcpy((ib_cpu + len), uve_rc_session_init, sizeof(uve_rc_session_init)); 315 len += sizeof(uve_rc_session_init) / 4; 316 317 memcpy((ib_cpu + len), uve_deblocking_filter, sizeof(uve_deblocking_filter)); 318 len += sizeof(uve_deblocking_filter) / 4; 319 320 memcpy((ib_cpu + len), uve_quality_params, sizeof(uve_quality_params)); 321 len += sizeof(uve_quality_params) / 4; 322 323 memcpy((ib_cpu + len), uve_op_init_rc, sizeof(uve_op_init_rc)); 324 len += sizeof(uve_op_init_rc) / 4; 325 326 memcpy((ib_cpu + len), uve_op_init_rc_vbv_level, sizeof(uve_op_init_rc_vbv_level)); 327 len += sizeof(uve_op_init_rc_vbv_level) / 4; 328 329 r = submit(len, AMDGPU_HW_IP_UVD_ENC); 330 CU_ASSERT_EQUAL(r, 0); 331} 332 333static void amdgpu_cs_uvd_enc_encode(void) 334{ 335 int len, r, i; 336 uint64_t luma_offset, chroma_offset; 337 uint32_t vbuf_size, bs_size = 0x003f4800, cpb_size; 338 unsigned align = (family_id >= AMDGPU_FAMILY_AI) ? 256 : 16; 339 vbuf_size = ALIGN(enc.width, align) * ALIGN(enc.height, 16) * 1.5; 340 cpb_size = vbuf_size * 10; 341 342 if (family_id < AMDGPU_FAMILY_AI || family_id >= AMDGPU_FAMILY_RV) 343 return; 344 345 num_resources = 0; 346 alloc_resource(&enc.fb, 4096, AMDGPU_GEM_DOMAIN_VRAM); 347 resources[num_resources++] = enc.fb.handle; 348 alloc_resource(&enc.bs, bs_size, AMDGPU_GEM_DOMAIN_VRAM); 349 resources[num_resources++] = enc.bs.handle; 350 alloc_resource(&enc.vbuf, vbuf_size, AMDGPU_GEM_DOMAIN_VRAM); 351 resources[num_resources++] = enc.vbuf.handle; 352 alloc_resource(&enc.cpb, cpb_size, AMDGPU_GEM_DOMAIN_VRAM); 353 resources[num_resources++] = enc.cpb.handle; 354 resources[num_resources++] = ib_handle; 355 356 r = amdgpu_bo_cpu_map(enc.vbuf.handle, (void **)&enc.vbuf.ptr); 357 CU_ASSERT_EQUAL(r, 0); 358 359 memset(enc.vbuf.ptr, 0, vbuf_size); 360 for (i = 0; i < enc.height; ++i) { 361 memcpy(enc.vbuf.ptr, (frame + i * enc.width), enc.width); 362 enc.vbuf.ptr += ALIGN(enc.width, align); 363 } 364 for (i = 0; i < enc.height / 2; ++i) { 365 memcpy(enc.vbuf.ptr, ((frame + enc.height * enc.width) + i * enc.width), enc.width); 366 enc.vbuf.ptr += ALIGN(enc.width, align); 367 } 368 369 r = amdgpu_bo_cpu_unmap(enc.vbuf.handle); 370 CU_ASSERT_EQUAL(r, 0); 371 372 len = 0; 373 memcpy((ib_cpu + len), uve_session_info, sizeof(uve_session_info)); 374 len += sizeof(uve_session_info) / 4; 375 ib_cpu[len++] = enc.session.addr >> 32; 376 ib_cpu[len++] = enc.session.addr; 377 378 memcpy((ib_cpu + len), uve_task_info, sizeof(uve_task_info)); 379 len += sizeof(uve_task_info) / 4; 380 ib_cpu[len++] = 0x000005e0; 381 ib_cpu[len++] = 0x00000001; 382 ib_cpu[len++] = 0x00000001; 383 384 memcpy((ib_cpu + len), uve_nalu_buffer_1, sizeof(uve_nalu_buffer_1)); 385 len += sizeof(uve_nalu_buffer_1) / 4; 386 387 memcpy((ib_cpu + len), uve_nalu_buffer_2, sizeof(uve_nalu_buffer_2)); 388 len += sizeof(uve_nalu_buffer_2) / 4; 389 390 memcpy((ib_cpu + len), uve_nalu_buffer_3, sizeof(uve_nalu_buffer_3)); 391 len += sizeof(uve_nalu_buffer_3) / 4; 392 393 memcpy((ib_cpu + len), uve_nalu_buffer_4, sizeof(uve_nalu_buffer_4)); 394 len += sizeof(uve_nalu_buffer_4) / 4; 395 396 memcpy((ib_cpu + len), uve_slice_header, sizeof(uve_slice_header)); 397 len += sizeof(uve_slice_header) / 4; 398 399 ib_cpu[len++] = 0x00000254; 400 ib_cpu[len++] = 0x00000010; 401 ib_cpu[len++] = enc.cpb.addr >> 32; 402 ib_cpu[len++] = enc.cpb.addr; 403 memcpy((ib_cpu + len), uve_ctx_buffer, sizeof(uve_ctx_buffer)); 404 len += sizeof(uve_ctx_buffer) / 4; 405 406 memcpy((ib_cpu + len), uve_bitstream_buffer, sizeof(uve_bitstream_buffer)); 407 len += sizeof(uve_bitstream_buffer) / 4; 408 ib_cpu[len++] = 0x00000000; 409 ib_cpu[len++] = enc.bs.addr >> 32; 410 ib_cpu[len++] = enc.bs.addr; 411 ib_cpu[len++] = 0x003f4800; 412 ib_cpu[len++] = 0x00000000; 413 414 memcpy((ib_cpu + len), uve_feedback_buffer, sizeof(uve_feedback_buffer)); 415 len += sizeof(uve_feedback_buffer) / 4; 416 ib_cpu[len++] = enc.fb.addr >> 32; 417 ib_cpu[len++] = enc.fb.addr; 418 ib_cpu[len++] = 0x00000010; 419 ib_cpu[len++] = 0x00000028; 420 421 memcpy((ib_cpu + len), uve_feedback_buffer_additional, sizeof(uve_feedback_buffer_additional)); 422 len += sizeof(uve_feedback_buffer_additional) / 4; 423 424 memcpy((ib_cpu + len), uve_intra_refresh, sizeof(uve_intra_refresh)); 425 len += sizeof(uve_intra_refresh) / 4; 426 427 memcpy((ib_cpu + len), uve_layer_select, sizeof(uve_layer_select)); 428 len += sizeof(uve_layer_select) / 4; 429 430 memcpy((ib_cpu + len), uve_rc_layer_init, sizeof(uve_rc_layer_init)); 431 len += sizeof(uve_rc_layer_init) / 4; 432 433 memcpy((ib_cpu + len), uve_layer_select, sizeof(uve_layer_select)); 434 len += sizeof(uve_layer_select) / 4; 435 436 memcpy((ib_cpu + len), uve_rc_per_pic, sizeof(uve_rc_per_pic)); 437 len += sizeof(uve_rc_per_pic) / 4; 438 439 unsigned luma_size = ALIGN(enc.width, align) * ALIGN(enc.height, 16); 440 luma_offset = enc.vbuf.addr; 441 chroma_offset = luma_offset + luma_size; 442 ib_cpu[len++] = 0x00000054; 443 ib_cpu[len++] = 0x0000000c; 444 ib_cpu[len++] = 0x00000002; 445 ib_cpu[len++] = 0x003f4800; 446 ib_cpu[len++] = luma_offset >> 32; 447 ib_cpu[len++] = luma_offset; 448 ib_cpu[len++] = chroma_offset >> 32; 449 ib_cpu[len++] = chroma_offset; 450 memcpy((ib_cpu + len), uve_encode_param, sizeof(uve_encode_param)); 451 len += sizeof(uve_encode_param) / 4; 452 453 memcpy((ib_cpu + len), uve_op_speed_enc_mode, sizeof(uve_op_speed_enc_mode)); 454 len += sizeof(uve_op_speed_enc_mode) / 4; 455 456 memcpy((ib_cpu + len), uve_op_encode, sizeof(uve_op_encode)); 457 len += sizeof(uve_op_encode) / 4; 458 459 r = submit(len, AMDGPU_HW_IP_UVD_ENC); 460 CU_ASSERT_EQUAL(r, 0); 461 462 check_result(&enc); 463 464 free_resource(&enc.fb); 465 free_resource(&enc.bs); 466 free_resource(&enc.vbuf); 467 free_resource(&enc.cpb); 468} 469 470static void amdgpu_cs_uvd_enc_destroy(void) 471{ 472 struct amdgpu_uvd_enc_bo sw_ctx; 473 int len, r; 474 475 if (family_id < AMDGPU_FAMILY_AI || family_id >= AMDGPU_FAMILY_RV) 476 return; 477 478 num_resources = 0; 479 resources[num_resources++] = ib_handle; 480 481 len = 0; 482 memcpy((ib_cpu + len), uve_session_info, sizeof(uve_session_info)); 483 len += sizeof(uve_session_info) / 4; 484 ib_cpu[len++] = enc.session.addr >> 32; 485 ib_cpu[len++] = enc.session.addr; 486 487 memcpy((ib_cpu + len), uve_task_info, sizeof(uve_task_info)); 488 len += sizeof(uve_task_info) / 4; 489 ib_cpu[len++] = 0xffffffff; 490 ib_cpu[len++] = 0x00000002; 491 ib_cpu[len++] = 0x00000000; 492 493 memcpy((ib_cpu + len), uve_op_close, sizeof(uve_op_close)); 494 len += sizeof(uve_op_close) / 4; 495 496 r = submit(len, AMDGPU_HW_IP_UVD_ENC); 497 CU_ASSERT_EQUAL(r, 0); 498 499 free_resource(&enc.session); 500} 501