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