2 * Copyright (C) 2020 Collabora Ltd.
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:
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
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 FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * Authors (Collabora):
24 * Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
28 #include "panfrost/lib/decode.h"
29 #include "drm-uapi/panfrost_drm.h"
30 #include "panfrost/lib/pan_encoder.h"
32 /* Standalone compiler tests submitting jobs directly to the hardware. Uses the
33 * `bit` prefix for `BIfrost Tests` and because bit sounds wicked cool. */
35 static struct panfrost_bo
*
36 bit_bo_create(struct panfrost_device
*dev
, size_t size
)
38 struct panfrost_bo
*bo
= panfrost_bo_create(dev
, size
, PAN_BO_EXECUTE
);
39 pandecode_inject_mmap(bo
->gpu
, bo
->cpu
, bo
->size
, NULL
);
43 struct panfrost_device
*
44 bit_initialize(void *memctx
)
46 int fd
= drmOpenWithType("panfrost", NULL
, DRM_NODE_RENDER
);
49 unreachable("No panfrost device found. Try chmod?");
51 struct panfrost_device
*dev
= rzalloc(memctx
, struct panfrost_device
);
52 panfrost_open_device(memctx
, fd
, dev
);
54 pandecode_initialize(true);
55 printf("%X\n", dev
->gpu_id
);
61 bit_submit(struct panfrost_device
*dev
,
63 void *payload
, size_t payload_size
,
64 struct panfrost_bo
**bos
, size_t bo_count
, enum bit_debug debug
)
66 struct mali_job_descriptor_header header
= {
67 .job_descriptor_size
= MALI_JOB_64
,
72 struct panfrost_bo
*job
= bit_bo_create(dev
, 4096);
73 memcpy(job
->cpu
, &header
, sizeof(header
));
74 memcpy(job
->cpu
+ sizeof(header
), payload
, payload_size
);
76 uint32_t *bo_handles
= calloc(sizeof(uint32_t), bo_count
);
78 for (unsigned i
= 0; i
< bo_count
; ++i
)
79 bo_handles
[i
] = bos
[i
]->gem_handle
;
84 ret
= drmSyncobjCreate(dev
->fd
, DRM_SYNCOBJ_CREATE_SIGNALED
, &syncobj
);
87 struct drm_panfrost_submit submit
= {
89 .bo_handles
= (uintptr_t) bo_handles
,
90 .bo_handle_count
= bo_count
,
94 ret
= drmIoctl(dev
->fd
, DRM_IOCTL_PANFROST_SUBMIT
, &submit
);
98 drmSyncobjWait(dev
->fd
, &syncobj
, 1, INT64_MAX
, 0, NULL
);
99 if (debug
>= BIT_DEBUG_ALL
)
100 pandecode_jc(submit
.jc
, true, dev
->gpu_id
, false);
104 /* Checks that the device is alive and responding to basic jobs as a sanity
105 * check - prerequisite to running code on the device. We test this via a
109 bit_sanity_check(struct panfrost_device
*dev
)
111 struct panfrost_bo
*scratch
= bit_bo_create(dev
, 65536);
112 ((uint32_t *) scratch
->cpu
)[0] = 0xAA;
114 struct mali_payload_write_value payload
= {
115 .address
= scratch
->gpu
,
116 .value_descriptor
= MALI_WRITE_VALUE_ZERO
119 struct panfrost_bo
*bos
[] = { scratch
};
120 bool success
= bit_submit(dev
, MALI_JOB_TYPE_WRITE_VALUE
,
121 &payload
, sizeof(payload
), bos
, 1, false);
123 return success
&& (((uint8_t *) scratch
->cpu
)[0] == 0x0);
126 /* Constructs a vertex job */
129 bit_vertex(struct panfrost_device
*dev
, panfrost_program prog
,
130 uint32_t *iubo
, size_t sz_ubo
,
131 uint32_t *iattr
, size_t sz_attr
,
132 uint32_t *expected
, size_t sz_expected
, enum bit_debug debug
)
135 struct panfrost_bo
*scratchpad
= bit_bo_create(dev
, 4096);
136 struct panfrost_bo
*shader
= bit_bo_create(dev
, prog
.compiled
.size
);
137 struct panfrost_bo
*shader_desc
= bit_bo_create(dev
, 4096);
138 struct panfrost_bo
*ubo
= bit_bo_create(dev
, 4096);
139 struct panfrost_bo
*var
= bit_bo_create(dev
, 4096);
140 struct panfrost_bo
*attr
= bit_bo_create(dev
, 4096);
142 pan_pack(var
->cpu
, ATTRIBUTE
, cfg
) {
143 cfg
.format
= (MALI_RGBA32UI
<< 12);
147 pan_pack(attr
->cpu
, ATTRIBUTE
, cfg
)
148 cfg
.format
= (MALI_RGBA32UI
<< 12);
150 pan_pack(var
->cpu
+ 256, ATTRIBUTE_BUFFER
, cfg
) {
151 cfg
.pointer
= (var
->gpu
+ 1024);
155 pan_pack(attr
->cpu
+ 256, ATTRIBUTE_BUFFER
, cfg
) {
156 cfg
.pointer
= (attr
->gpu
+ 1024);
161 memcpy(ubo
->cpu
+ 1024, iubo
, sz_ubo
);
164 memcpy(attr
->cpu
+ 1024, iattr
, sz_attr
);
166 struct panfrost_bo
*shmem
= bit_bo_create(dev
, 4096);
167 struct mali_shared_memory shmemp
= {
168 .scratchpad
= scratchpad
->gpu
,
169 .shared_workgroup_count
= 0x1f,
172 memcpy(shmem
->cpu
, &shmemp
, sizeof(shmemp
));
174 pan_pack(shader_desc
->cpu
, STATE
, cfg
) {
175 cfg
.shader
.shader
= shader
->gpu
;
176 cfg
.shader
.attribute_count
= cfg
.shader
.varying_count
= 1;
177 cfg
.properties
= 0x80020001;
178 cfg
.preload
.uniform_count
= (sz_ubo
/ 16);
181 memcpy(shader
->cpu
, prog
.compiled
.data
, prog
.compiled
.size
);
183 struct bifrost_payload_vertex payload
= {
186 .opaque
= { (5) << 26 }
191 .shared_memory
= shmem
->gpu
,
192 .shader
= shader_desc
->gpu
,
193 .uniforms
= ubo
->gpu
+ 1024,
194 .uniform_buffers
= ubo
->gpu
,
195 .attribute_meta
= attr
->gpu
,
196 .attributes
= attr
->gpu
+ 256,
197 .varying_meta
= var
->gpu
,
198 .varyings
= var
->gpu
+ 256,
202 panfrost_pack_work_groups_compute(&payload
.prefix
,
207 struct panfrost_bo
*bos
[] = {
208 scratchpad
, shmem
, shader
, shader_desc
, ubo
, var
, attr
211 bool succ
= bit_submit(dev
, MALI_JOB_TYPE_VERTEX
, &payload
,
212 sizeof(payload
), bos
, ARRAY_SIZE(bos
), debug
);
214 /* Check the output varyings */
216 uint32_t *output
= (uint32_t *) (var
->cpu
+ 1024);
217 float *foutput
= (float *) output
;
218 float *fexpected
= (float *) expected
;
221 unsigned comp
= memcmp(output
, expected
, sz_expected
);
224 if (comp
&& (debug
>= BIT_DEBUG_FAIL
)) {
225 fprintf(stderr
, "expected [");
227 for (unsigned i
= 0; i
< (sz_expected
>> 2); ++i
)
228 fprintf(stderr
, "%08X /* %f */ ", expected
[i
], fexpected
[i
]);
230 fprintf(stderr
, "], got [");
232 for (unsigned i
= 0; i
< (sz_expected
>> 2); ++i
)
233 fprintf(stderr
, "%08X /* %f */ ", output
[i
], foutput
[i
]);
235 fprintf(stderr
, "\n");
237 } else if (debug
== BIT_DEBUG_ALL
) {
238 fprintf(stderr
, "got [");
240 for (unsigned i
= 0; i
< 4; ++i
)
241 fprintf(stderr
, "%08X /* %f */ ", output
[i
], foutput
[i
]);
243 fprintf(stderr
, "\n");