pan/bit: Begin generating a vertex job
[mesa.git] / src / panfrost / bifrost / test / bi_submit.c
1 /*
2 * Copyright (C) 2020 Collabora Ltd.
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 (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
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
21 * SOFTWARE.
22 *
23 * Authors (Collabora):
24 * Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
25 */
26
27 #include "bit.h"
28 #include "panfrost/pandecode/decode.h"
29 #include "drm-uapi/panfrost_drm.h"
30 #include "panfrost/encoder/pan_encoder.h"
31
32 /* Standalone compiler tests submitting jobs directly to the hardware. Uses the
33 * `bit` prefix for `BIfrost Tests` and because bit sounds wicked cool. */
34
35 static struct panfrost_bo *
36 bit_bo_create(struct panfrost_device *dev, size_t size)
37 {
38 struct panfrost_bo *bo = panfrost_bo_create(dev, size, PAN_BO_EXECUTE);
39 pandecode_inject_mmap(bo->gpu, bo->cpu, bo->size, NULL);
40 return bo;
41 }
42
43 struct panfrost_device *
44 bit_initialize(void *memctx)
45 {
46 int fd = drmOpenWithType("panfrost", NULL, DRM_NODE_RENDER);
47
48 if (fd < 0)
49 unreachable("No panfrost device found. Try chmod?");
50
51 struct panfrost_device *dev = rzalloc(memctx, struct panfrost_device);
52 panfrost_open_device(memctx, fd, dev);
53
54 pandecode_initialize(true);
55 printf("%X\n", dev->gpu_id);
56
57 return dev;
58 }
59
60 static bool
61 bit_submit(struct panfrost_device *dev,
62 enum mali_job_type T,
63 void *payload, size_t payload_size,
64 struct panfrost_bo **bos, size_t bo_count, bool trace)
65 {
66 struct mali_job_descriptor_header header = {
67 .job_descriptor_size = MALI_JOB_64,
68 .job_type = T,
69 .job_index = 1
70 };
71
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);
75
76 uint32_t *bo_handles = calloc(sizeof(uint32_t), bo_count);
77
78 for (unsigned i = 0; i < bo_count; ++i)
79 bo_handles[i] = bos[i]->gem_handle;
80
81 uint32_t syncobj = 0;
82 int ret = 0;
83
84 ret = drmSyncobjCreate(dev->fd, DRM_SYNCOBJ_CREATE_SIGNALED, &syncobj);
85 assert(!ret);
86
87 struct drm_panfrost_submit submit = {
88 .jc = job->gpu,
89 .bo_handles = (uintptr_t) bo_handles,
90 .bo_handle_count = bo_count,
91 .out_sync = syncobj,
92 };
93
94 ret = drmIoctl(dev->fd, DRM_IOCTL_PANFROST_SUBMIT, &submit);
95 assert(!ret);
96 free(bo_handles);
97
98 drmSyncobjWait(dev->fd, &syncobj, 1, INT64_MAX, 0, NULL);
99 if (trace)
100 pandecode_jc(submit.jc, true, dev->gpu_id, false);
101 return true;
102 }
103
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
106 * WRITE_VALUE job */
107
108 bool
109 bit_sanity_check(struct panfrost_device *dev)
110 {
111 struct panfrost_bo *scratch = bit_bo_create(dev, 65536);
112 ((uint32_t *) scratch->cpu)[0] = 0xAA;
113
114 struct mali_payload_write_value payload = {
115 .address = scratch->gpu,
116 .value_descriptor = MALI_WRITE_VALUE_ZERO
117 };
118
119 struct panfrost_bo *bos[] = { scratch };
120 bool success = bit_submit(dev, JOB_TYPE_WRITE_VALUE,
121 &payload, sizeof(payload), bos, 1, false);
122
123 return success && (((uint8_t *) scratch->cpu)[0] == 0x0);
124 }
125
126 /* Constructs a vertex job */
127
128 bool
129 bit_vertex(struct panfrost_device *dev, panfrost_program prog)
130 {
131
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);
138
139 struct mali_attr_meta vmeta = {
140 .index = 0,
141 .format = MALI_RGBA32F
142 };
143
144 union mali_attr vary = {
145 .elements = (var->gpu + 1024) | MALI_ATTR_LINEAR,
146 .size = 1024
147 };
148
149 union mali_attr attr_ = {
150 .elements = (attr->gpu + 1024) | MALI_ATTR_LINEAR,
151 .size = 1024
152 };
153
154 uint64_t my_ubo = MALI_MAKE_UBO(64, ubo->gpu + 1024);
155
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));
161
162 float *fvaryings = (float *) (var->cpu + 1024);
163 float *fubo = (float *) (ubo->cpu + 1024);
164
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,
169 };
170
171 memcpy(shmem->cpu, &shmemp, sizeof(shmemp));
172
173 struct mali_shader_meta meta = {
174 .shader = shader->gpu,
175 .attribute_count = 1,
176 .varying_count = 1,
177 .bifrost1 = {
178 .unk1 = 0x800200,
179 },
180 .bifrost2 = {
181 .unk3 = 0x0,
182 .preload_regs = 0xc0,
183 .uniform_count = 0,
184 .unk4 = 0x0,
185 },
186 };
187
188 memcpy(shader_desc->cpu, &meta, sizeof(meta));
189 memcpy(shader->cpu, prog.compiled.data, prog.compiled.size);
190
191 struct bifrost_payload_vertex payload = {
192 .prefix = {
193 },
194 .vertex = {
195 .unk2 = 0x2,
196 },
197 .postfix = {
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,
206 },
207 };
208
209 panfrost_pack_work_groups_compute(&payload.prefix,
210 1, 1, 1,
211 1, 1, 1,
212 true);
213
214 payload.prefix.workgroups_x_shift_3 = 5;
215
216 struct panfrost_bo *bos[] = {
217 scratchpad, shmem, shader, shader_desc, ubo, var, attr
218 };
219
220 return bit_submit(dev, JOB_TYPE_VERTEX, &payload,
221 sizeof(payload), bos, ARRAY_SIZE(bos), true);
222 }