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
, bool trace
)
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
);
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
)
132 struct panfrost_bo
*scratchpad
= bit_bo_create(dev
, 4096);
133 struct panfrost_bo
*shader
= bit_bo_create(dev
, prog
.compiled
.size
);
134 struct panfrost_bo
*shader_desc
= bit_bo_create(dev
, 4096);
135 struct panfrost_bo
*ubo
= bit_bo_create(dev
, 4096);
136 struct panfrost_bo
*var
= bit_bo_create(dev
, 4096);
137 struct panfrost_bo
*attr
= bit_bo_create(dev
, 4096);
139 struct mali_attr_meta vmeta
= {
141 .format
= MALI_RGBA32F
144 union mali_attr vary
= {
145 .elements
= (var
->gpu
+ 1024) | MALI_ATTR_LINEAR
,
149 union mali_attr attr_
= {
150 .elements
= (attr
->gpu
+ 1024) | MALI_ATTR_LINEAR
,
154 uint64_t my_ubo
= MALI_MAKE_UBO(64, ubo
->gpu
+ 1024);
156 memcpy(ubo
->cpu
, &my_ubo
, sizeof(my_ubo
));
157 memcpy(var
->cpu
, &vmeta
, sizeof(vmeta
));
158 memcpy(attr
->cpu
, &vmeta
, sizeof(vmeta
));
159 memcpy(var
->cpu
+ 256, &vary
, sizeof(vary
));
160 memcpy(attr
->cpu
+ 256, &attr_
, sizeof(vary
));
162 float *fvaryings
= (float *) (var
->cpu
+ 1024);
163 float *fubo
= (float *) (ubo
->cpu
+ 1024);
165 struct panfrost_bo
*shmem
= bit_bo_create(dev
, 4096);
166 struct mali_shared_memory shmemp
= {
167 .scratchpad
= scratchpad
->gpu
,
168 .shared_workgroup_count
= 0x1f,
171 memcpy(shmem
->cpu
, &shmemp
, sizeof(shmemp
));
173 struct mali_shader_meta meta
= {
174 .shader
= shader
->gpu
,
175 .attribute_count
= 1,
182 .preload_regs
= 0xc0,
188 memcpy(shader_desc
->cpu
, &meta
, sizeof(meta
));
189 memcpy(shader
->cpu
, prog
.compiled
.data
, prog
.compiled
.size
);
191 struct bifrost_payload_vertex payload
= {
198 .shared_memory
= shmem
->gpu
,
199 .shader
= shader_desc
->gpu
,
200 .uniforms
= ubo
->gpu
+ 1024,
201 .uniform_buffers
= ubo
->gpu
,
202 .attribute_meta
= attr
->gpu
,
203 .attributes
= var
->gpu
+ 256,
204 .varying_meta
= var
->gpu
,
205 .varyings
= var
->gpu
+ 256,
209 panfrost_pack_work_groups_compute(&payload
.prefix
,
214 payload
.prefix
.workgroups_x_shift_3
= 5;
216 struct panfrost_bo
*bos
[] = {
217 scratchpad
, shmem
, shader
, shader_desc
, ubo
, var
, attr
220 return bit_submit(dev
, JOB_TYPE_VERTEX
, &payload
,
221 sizeof(payload
), bos
, ARRAY_SIZE(bos
), true);