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/pandecode/decode.h"
29 #include "drm-uapi/panfrost_drm.h"
30 #include "panfrost/encoder/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
, 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 struct mali_attr_meta vmeta
= {
144 .format
= MALI_RGBA32UI
147 union mali_attr vary
= {
148 .elements
= (var
->gpu
+ 1024) | MALI_ATTR_LINEAR
,
152 union mali_attr attr_
= {
153 .elements
= (attr
->gpu
+ 1024) | MALI_ATTR_LINEAR
,
157 uint64_t my_ubo
= MALI_MAKE_UBO(64, ubo
->gpu
+ 1024);
159 memcpy(ubo
->cpu
, &my_ubo
, sizeof(my_ubo
));
160 memcpy(var
->cpu
, &vmeta
, sizeof(vmeta
));
162 vmeta
.unknown1
= 0x2; /* XXX: only attrib? */
163 memcpy(attr
->cpu
, &vmeta
, sizeof(vmeta
));
164 memcpy(var
->cpu
+ 256, &vary
, sizeof(vary
));
165 memcpy(attr
->cpu
+ 256, &attr_
, sizeof(vary
));
168 memcpy(ubo
->cpu
+ 1024, iubo
, sz_ubo
);
171 memcpy(attr
->cpu
+ 1024, iattr
, sz_attr
);
173 struct panfrost_bo
*shmem
= bit_bo_create(dev
, 4096);
174 struct mali_shared_memory shmemp
= {
175 .scratchpad
= scratchpad
->gpu
,
176 .shared_workgroup_count
= 0x1f,
179 memcpy(shmem
->cpu
, &shmemp
, sizeof(shmemp
));
181 struct mali_shader_meta meta
= {
182 .shader
= shader
->gpu
,
183 .attribute_count
= 1,
187 .uniform_buffer_count
= 1,
191 .preload_regs
= 0xc0,
192 .uniform_count
= sz_ubo
/ 16,
197 memcpy(shader_desc
->cpu
, &meta
, sizeof(meta
));
198 memcpy(shader
->cpu
, prog
.compiled
.data
, prog
.compiled
.size
);
200 struct bifrost_payload_vertex payload
= {
205 .shared_memory
= shmem
->gpu
,
206 .shader
= shader_desc
->gpu
,
207 .uniforms
= ubo
->gpu
+ 1024,
208 .uniform_buffers
= ubo
->gpu
,
209 .attribute_meta
= attr
->gpu
,
210 .attributes
= attr
->gpu
+ 256,
211 .varying_meta
= var
->gpu
,
212 .varyings
= var
->gpu
+ 256,
216 panfrost_pack_work_groups_compute(&payload
.prefix
,
221 payload
.prefix
.workgroups_x_shift_3
= 5;
223 struct panfrost_bo
*bos
[] = {
224 scratchpad
, shmem
, shader
, shader_desc
, ubo
, var
, attr
227 bool succ
= bit_submit(dev
, JOB_TYPE_VERTEX
, &payload
,
228 sizeof(payload
), bos
, ARRAY_SIZE(bos
), debug
);
230 /* Check the output varyings */
232 uint32_t *output
= (uint32_t *) (var
->cpu
+ 1024);
233 float *foutput
= (float *) output
;
234 float *fexpected
= (float *) expected
;
237 unsigned comp
= memcmp(output
, expected
, sz_expected
);
240 if (comp
&& (debug
>= BIT_DEBUG_FAIL
)) {
241 fprintf(stderr
, "expected [");
243 for (unsigned i
= 0; i
< (sz_expected
>> 2); ++i
)
244 fprintf(stderr
, "%08X /* %f */ ", expected
[i
], fexpected
[i
]);
246 fprintf(stderr
, "], got [");
248 for (unsigned i
= 0; i
< (sz_expected
>> 2); ++i
)
249 fprintf(stderr
, "%08X /* %f */ ", output
[i
], foutput
[i
]);
251 fprintf(stderr
, "\n");
253 } else if (debug
== BIT_DEBUG_ALL
) {
254 fprintf(stderr
, "got [");
256 for (unsigned i
= 0; i
< 4; ++i
)
257 fprintf(stderr
, "%08X /* %f */ ", output
[i
], foutput
[i
]);
259 fprintf(stderr
, "\n");