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