~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/freedreno/computerator/a6xx.c

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright © 2020 Google, 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 (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
 
 
24
 
#include "ir3/ir3_compiler.h"
25
 
 
26
 
#include "util/u_math.h"
27
 
 
28
 
#include "adreno_pm4.xml.h"
29
 
#include "adreno_common.xml.h"
30
 
#include "a6xx.xml.h"
31
 
 
32
 
#include "common/freedreno_dev_info.h"
33
 
 
34
 
#include "ir3_asm.h"
35
 
#include "main.h"
36
 
 
37
 
struct a6xx_backend {
38
 
   struct backend base;
39
 
 
40
 
   struct ir3_compiler *compiler;
41
 
   struct fd_device *dev;
42
 
 
43
 
   const struct fd_dev_info *info;
44
 
 
45
 
   unsigned seqno;
46
 
   struct fd_bo *control_mem;
47
 
 
48
 
   struct fd_bo *query_mem;
49
 
   const struct perfcntr *perfcntrs;
50
 
   unsigned num_perfcntrs;
51
 
};
52
 
define_cast(backend, a6xx_backend);
53
 
 
54
 
/*
55
 
 * Data structures shared with GPU:
56
 
 */
57
 
 
58
 
/* This struct defines the layout of the fd6_context::control buffer: */
59
 
struct fd6_control {
60
 
   uint32_t seqno; /* seqno for async CP_EVENT_WRITE, etc */
61
 
   uint32_t _pad0;
62
 
   volatile uint32_t vsc_overflow;
63
 
   uint32_t _pad1;
64
 
   /* flag set from cmdstream when VSC overflow detected: */
65
 
   uint32_t vsc_scratch;
66
 
   uint32_t _pad2;
67
 
   uint32_t _pad3;
68
 
   uint32_t _pad4;
69
 
 
70
 
   /* scratch space for VPC_SO[i].FLUSH_BASE_LO/HI, start on 32 byte boundary. */
71
 
   struct {
72
 
      uint32_t offset;
73
 
      uint32_t pad[7];
74
 
   } flush_base[4];
75
 
};
76
 
 
77
 
#define control_ptr(a6xx_backend, member)                                      \
78
 
   (a6xx_backend)->control_mem, offsetof(struct fd6_control, member), 0, 0
79
 
 
80
 
struct PACKED fd6_query_sample {
81
 
   uint64_t start;
82
 
   uint64_t result;
83
 
   uint64_t stop;
84
 
};
85
 
 
86
 
/* offset of a single field of an array of fd6_query_sample: */
87
 
#define query_sample_idx(a6xx_backend, idx, field)                             \
88
 
   (a6xx_backend)->query_mem,                                                  \
89
 
      (idx * sizeof(struct fd6_query_sample)) +                                \
90
 
         offsetof(struct fd6_query_sample, field),                             \
91
 
      0, 0
92
 
 
93
 
/*
94
 
 * Backend implementation:
95
 
 */
96
 
 
97
 
static struct kernel *
98
 
a6xx_assemble(struct backend *b, FILE *in)
99
 
{
100
 
   struct a6xx_backend *a6xx_backend = to_a6xx_backend(b);
101
 
   struct ir3_kernel *ir3_kernel = ir3_asm_assemble(a6xx_backend->compiler, in);
102
 
   ir3_kernel->backend = b;
103
 
   return &ir3_kernel->base;
104
 
}
105
 
 
106
 
static void
107
 
a6xx_disassemble(struct kernel *kernel, FILE *out)
108
 
{
109
 
   ir3_asm_disassemble(to_ir3_kernel(kernel), out);
110
 
}
111
 
 
112
 
static void
113
 
cs_program_emit(struct fd_ringbuffer *ring, struct kernel *kernel)
114
 
{
115
 
   struct ir3_kernel *ir3_kernel = to_ir3_kernel(kernel);
116
 
   struct a6xx_backend *a6xx_backend = to_a6xx_backend(ir3_kernel->backend);
117
 
   struct ir3_shader_variant *v = ir3_kernel->v;
118
 
   const struct ir3_info *i = &v->info;
119
 
   enum a6xx_threadsize thrsz = i->double_threadsize ? THREAD128 : THREAD64;
120
 
 
121
 
   OUT_PKT4(ring, REG_A6XX_SP_MODE_CONTROL, 1);
122
 
   OUT_RING(ring, A6XX_SP_MODE_CONTROL_CONSTANT_DEMOTION_ENABLE | 4);
123
 
 
124
 
   OUT_PKT4(ring, REG_A6XX_SP_PERFCTR_ENABLE, 1);
125
 
   OUT_RING(ring, A6XX_SP_PERFCTR_ENABLE_CS);
126
 
 
127
 
   OUT_PKT4(ring, REG_A6XX_SP_FLOAT_CNTL, 1);
128
 
   OUT_RING(ring, 0);
129
 
 
130
 
   OUT_PKT4(ring, REG_A6XX_HLSQ_INVALIDATE_CMD, 1);
131
 
   OUT_RING(
132
 
      ring,
133
 
      A6XX_HLSQ_INVALIDATE_CMD_VS_STATE | A6XX_HLSQ_INVALIDATE_CMD_HS_STATE |
134
 
         A6XX_HLSQ_INVALIDATE_CMD_DS_STATE | A6XX_HLSQ_INVALIDATE_CMD_GS_STATE |
135
 
         A6XX_HLSQ_INVALIDATE_CMD_FS_STATE | A6XX_HLSQ_INVALIDATE_CMD_CS_STATE |
136
 
         A6XX_HLSQ_INVALIDATE_CMD_CS_IBO | A6XX_HLSQ_INVALIDATE_CMD_GFX_IBO);
137
 
 
138
 
   unsigned constlen = align(v->constlen, 4);
139
 
   OUT_PKT4(ring, REG_A6XX_HLSQ_CS_CNTL, 1);
140
 
   OUT_RING(ring,
141
 
            A6XX_HLSQ_CS_CNTL_CONSTLEN(constlen) | A6XX_HLSQ_CS_CNTL_ENABLED);
142
 
 
143
 
   OUT_PKT4(ring, REG_A6XX_SP_CS_CONFIG, 2);
144
 
   OUT_RING(ring, A6XX_SP_CS_CONFIG_ENABLED |
145
 
                     A6XX_SP_CS_CONFIG_NIBO(kernel->num_bufs) |
146
 
                     A6XX_SP_CS_CONFIG_NTEX(v->num_samp) |
147
 
                     A6XX_SP_CS_CONFIG_NSAMP(v->num_samp)); /* SP_VS_CONFIG */
148
 
   OUT_RING(ring, v->instrlen);                             /* SP_VS_INSTRLEN */
149
 
 
150
 
   OUT_PKT4(ring, REG_A6XX_SP_CS_CTRL_REG0, 1);
151
 
   OUT_RING(ring,
152
 
            A6XX_SP_CS_CTRL_REG0_THREADSIZE(thrsz) |
153
 
               A6XX_SP_CS_CTRL_REG0_FULLREGFOOTPRINT(i->max_reg + 1) |
154
 
               A6XX_SP_CS_CTRL_REG0_HALFREGFOOTPRINT(i->max_half_reg + 1) |
155
 
               COND(v->mergedregs, A6XX_SP_CS_CTRL_REG0_MERGEDREGS) |
156
 
               A6XX_SP_CS_CTRL_REG0_BRANCHSTACK(ir3_shader_branchstack_hw(v)));
157
 
 
158
 
   OUT_PKT4(ring, REG_A6XX_SP_CS_UNKNOWN_A9B1, 1);
159
 
   OUT_RING(ring, 0x41);
160
 
 
161
 
   if (a6xx_backend->info->a6xx.has_lpac) {
162
 
      OUT_PKT4(ring, REG_A6XX_HLSQ_CS_UNKNOWN_B9D0, 1);
163
 
      OUT_RING(ring, A6XX_HLSQ_CS_UNKNOWN_B9D0_SHARED_SIZE(1) |
164
 
                        A6XX_HLSQ_CS_UNKNOWN_B9D0_UNK6);
165
 
   }
166
 
 
167
 
   uint32_t local_invocation_id, work_group_id;
168
 
   local_invocation_id =
169
 
      ir3_find_sysval_regid(v, SYSTEM_VALUE_LOCAL_INVOCATION_ID);
170
 
   work_group_id = ir3_find_sysval_regid(v, SYSTEM_VALUE_WORKGROUP_ID);
171
 
 
172
 
   OUT_PKT4(ring, REG_A6XX_HLSQ_CS_CNTL_0, 2);
173
 
   OUT_RING(ring, A6XX_HLSQ_CS_CNTL_0_WGIDCONSTID(work_group_id) |
174
 
                     A6XX_HLSQ_CS_CNTL_0_WGSIZECONSTID(regid(63, 0)) |
175
 
                     A6XX_HLSQ_CS_CNTL_0_WGOFFSETCONSTID(regid(63, 0)) |
176
 
                     A6XX_HLSQ_CS_CNTL_0_LOCALIDREGID(local_invocation_id));
177
 
   OUT_RING(ring, A6XX_HLSQ_CS_CNTL_1_LINEARLOCALIDREGID(regid(63, 0)) |
178
 
                     A6XX_HLSQ_CS_CNTL_1_THREADSIZE(thrsz));
179
 
 
180
 
   if (a6xx_backend->info->a6xx.has_lpac) {
181
 
      OUT_PKT4(ring, REG_A6XX_SP_CS_CNTL_0, 2);
182
 
      OUT_RING(ring, A6XX_SP_CS_CNTL_0_WGIDCONSTID(work_group_id) |
183
 
                        A6XX_SP_CS_CNTL_0_WGSIZECONSTID(regid(63, 0)) |
184
 
                        A6XX_SP_CS_CNTL_0_WGOFFSETCONSTID(regid(63, 0)) |
185
 
                        A6XX_SP_CS_CNTL_0_LOCALIDREGID(local_invocation_id));
186
 
      OUT_RING(ring, A6XX_SP_CS_CNTL_1_LINEARLOCALIDREGID(regid(63, 0)) |
187
 
                        A6XX_SP_CS_CNTL_1_THREADSIZE(thrsz));
188
 
   }
189
 
 
190
 
   OUT_PKT4(ring, REG_A6XX_SP_CS_OBJ_START, 2);
191
 
   OUT_RELOC(ring, v->bo, 0, 0, 0); /* SP_CS_OBJ_START_LO/HI */
192
 
 
193
 
   OUT_PKT4(ring, REG_A6XX_SP_CS_INSTRLEN, 1);
194
 
   OUT_RING(ring, v->instrlen);
195
 
 
196
 
   OUT_PKT4(ring, REG_A6XX_SP_CS_OBJ_START, 2);
197
 
   OUT_RELOC(ring, v->bo, 0, 0, 0);
198
 
 
199
 
   uint32_t shader_preload_size =
200
 
      MIN2(v->instrlen, a6xx_backend->info->a6xx.instr_cache_size);
201
 
   OUT_PKT7(ring, CP_LOAD_STATE6_FRAG, 3);
202
 
   OUT_RING(ring, CP_LOAD_STATE6_0_DST_OFF(0) |
203
 
                     CP_LOAD_STATE6_0_STATE_TYPE(ST6_SHADER) |
204
 
                     CP_LOAD_STATE6_0_STATE_SRC(SS6_INDIRECT) |
205
 
                     CP_LOAD_STATE6_0_STATE_BLOCK(SB6_CS_SHADER) |
206
 
                     CP_LOAD_STATE6_0_NUM_UNIT(shader_preload_size));
207
 
   OUT_RELOC(ring, v->bo, 0, 0, 0);
208
 
 
209
 
   if (v->pvtmem_size > 0) {
210
 
      uint32_t per_fiber_size = ALIGN(v->pvtmem_size, 512);
211
 
      uint32_t per_sp_size =
212
 
         ALIGN(per_fiber_size * a6xx_backend->info->a6xx.fibers_per_sp, 1 << 12);
213
 
      uint32_t total_size = per_sp_size * a6xx_backend->info->num_sp_cores;
214
 
 
215
 
      struct fd_bo *pvtmem = fd_bo_new(a6xx_backend->dev, total_size, 0, "pvtmem");
216
 
      OUT_PKT4(ring, REG_A6XX_SP_CS_PVT_MEM_PARAM, 4);
217
 
      OUT_RING(ring, A6XX_SP_CS_PVT_MEM_PARAM_MEMSIZEPERITEM(per_fiber_size));
218
 
      OUT_RELOC(ring, pvtmem, 0, 0, 0);
219
 
      OUT_RING(ring, A6XX_SP_CS_PVT_MEM_SIZE_TOTALPVTMEMSIZE(per_sp_size) |
220
 
                     COND(v->pvtmem_per_wave,
221
 
                          A6XX_SP_CS_PVT_MEM_SIZE_PERWAVEMEMLAYOUT));
222
 
 
223
 
      OUT_PKT4(ring, REG_A6XX_SP_CS_PVT_MEM_HW_STACK_OFFSET, 1);
224
 
      OUT_RING(ring, A6XX_SP_CS_PVT_MEM_HW_STACK_OFFSET_OFFSET(per_sp_size));
225
 
   }
226
 
}
227
 
 
228
 
static void
229
 
emit_const(struct fd_ringbuffer *ring, uint32_t regid, uint32_t sizedwords,
230
 
           const uint32_t *dwords)
231
 
{
232
 
   uint32_t align_sz;
233
 
 
234
 
   debug_assert((regid % 4) == 0);
235
 
 
236
 
   align_sz = align(sizedwords, 4);
237
 
 
238
 
   OUT_PKT7(ring, CP_LOAD_STATE6_FRAG, 3 + align_sz);
239
 
   OUT_RING(ring, CP_LOAD_STATE6_0_DST_OFF(regid / 4) |
240
 
                     CP_LOAD_STATE6_0_STATE_TYPE(ST6_CONSTANTS) |
241
 
                     CP_LOAD_STATE6_0_STATE_SRC(SS6_DIRECT) |
242
 
                     CP_LOAD_STATE6_0_STATE_BLOCK(SB6_CS_SHADER) |
243
 
                     CP_LOAD_STATE6_0_NUM_UNIT(DIV_ROUND_UP(sizedwords, 4)));
244
 
   OUT_RING(ring, CP_LOAD_STATE6_1_EXT_SRC_ADDR(0));
245
 
   OUT_RING(ring, CP_LOAD_STATE6_2_EXT_SRC_ADDR_HI(0));
246
 
 
247
 
   for (uint32_t i = 0; i < sizedwords; i++) {
248
 
      OUT_RING(ring, dwords[i]);
249
 
   }
250
 
 
251
 
   /* Zero-pad to multiple of 4 dwords */
252
 
   for (uint32_t i = sizedwords; i < align_sz; i++) {
253
 
      OUT_RING(ring, 0);
254
 
   }
255
 
}
256
 
 
257
 
static void
258
 
cs_const_emit(struct fd_ringbuffer *ring, struct kernel *kernel,
259
 
              uint32_t grid[3])
260
 
{
261
 
   struct ir3_kernel *ir3_kernel = to_ir3_kernel(kernel);
262
 
   struct ir3_shader_variant *v = ir3_kernel->v;
263
 
 
264
 
   const struct ir3_const_state *const_state = ir3_const_state(v);
265
 
   uint32_t base = const_state->offsets.immediate;
266
 
   int size = DIV_ROUND_UP(const_state->immediates_count, 4);
267
 
 
268
 
   if (ir3_kernel->info.numwg != INVALID_REG) {
269
 
      assert((ir3_kernel->info.numwg & 0x3) == 0);
270
 
      int idx = ir3_kernel->info.numwg >> 2;
271
 
      const_state->immediates[idx * 4 + 0] = grid[0];
272
 
      const_state->immediates[idx * 4 + 1] = grid[1];
273
 
      const_state->immediates[idx * 4 + 2] = grid[2];
274
 
   }
275
 
 
276
 
   for (int i = 0; i < MAX_BUFS; i++) {
277
 
      if (kernel->buf_addr_regs[i] != INVALID_REG) {
278
 
         assert((kernel->buf_addr_regs[i] & 0x3) == 0);
279
 
         int idx = kernel->buf_addr_regs[i] >> 2;
280
 
 
281
 
         uint64_t iova = fd_bo_get_iova(kernel->bufs[i]);
282
 
 
283
 
         const_state->immediates[idx * 4 + 1] = iova >> 32;
284
 
         const_state->immediates[idx * 4 + 0] = (iova << 32) >> 32;
285
 
      }
286
 
   }
287
 
 
288
 
   /* truncate size to avoid writing constants that shader
289
 
    * does not use:
290
 
    */
291
 
   size = MIN2(size + base, v->constlen) - base;
292
 
 
293
 
   /* convert out of vec4: */
294
 
   base *= 4;
295
 
   size *= 4;
296
 
 
297
 
   if (size > 0) {
298
 
      emit_const(ring, base, size, const_state->immediates);
299
 
   }
300
 
}
301
 
 
302
 
static void
303
 
cs_ibo_emit(struct fd_ringbuffer *ring, struct fd_submit *submit,
304
 
            struct kernel *kernel)
305
 
{
306
 
   struct fd_ringbuffer *state = fd_submit_new_ringbuffer(
307
 
      submit, kernel->num_bufs * 16 * 4, FD_RINGBUFFER_STREAMING);
308
 
 
309
 
   for (unsigned i = 0; i < kernel->num_bufs; i++) {
310
 
      /* size is encoded with low 15b in WIDTH and high bits in HEIGHT,
311
 
       * in units of elements:
312
 
       */
313
 
      unsigned sz = kernel->buf_sizes[i];
314
 
      unsigned width = sz & MASK(15);
315
 
      unsigned height = sz >> 15;
316
 
 
317
 
      OUT_RING(state, A6XX_TEX_CONST_0_FMT(FMT6_32_UINT) | A6XX_TEX_CONST_0_TILE_MODE(0));
318
 
      OUT_RING(state, A6XX_TEX_CONST_1_WIDTH(width) | A6XX_TEX_CONST_1_HEIGHT(height));
319
 
      OUT_RING(state, A6XX_TEX_CONST_2_PITCH(0) | A6XX_TEX_CONST_2_BUFFER |
320
 
                         A6XX_TEX_CONST_2_TYPE(A6XX_TEX_BUFFER));
321
 
      OUT_RING(state, A6XX_TEX_CONST_3_ARRAY_PITCH(0));
322
 
      OUT_RELOC(state, kernel->bufs[i], 0, 0, 0);
323
 
      OUT_RING(state, 0x00000000);
324
 
      OUT_RING(state, 0x00000000);
325
 
      OUT_RING(state, 0x00000000);
326
 
      OUT_RING(state, 0x00000000);
327
 
      OUT_RING(state, 0x00000000);
328
 
      OUT_RING(state, 0x00000000);
329
 
      OUT_RING(state, 0x00000000);
330
 
      OUT_RING(state, 0x00000000);
331
 
      OUT_RING(state, 0x00000000);
332
 
      OUT_RING(state, 0x00000000);
333
 
   }
334
 
 
335
 
   OUT_PKT7(ring, CP_LOAD_STATE6_FRAG, 3);
336
 
   OUT_RING(ring, CP_LOAD_STATE6_0_DST_OFF(0) |
337
 
                     CP_LOAD_STATE6_0_STATE_TYPE(ST6_IBO) |
338
 
                     CP_LOAD_STATE6_0_STATE_SRC(SS6_INDIRECT) |
339
 
                     CP_LOAD_STATE6_0_STATE_BLOCK(SB6_CS_SHADER) |
340
 
                     CP_LOAD_STATE6_0_NUM_UNIT(kernel->num_bufs));
341
 
   OUT_RB(ring, state);
342
 
 
343
 
   OUT_PKT4(ring, REG_A6XX_SP_CS_IBO, 2);
344
 
   OUT_RB(ring, state);
345
 
 
346
 
   OUT_PKT4(ring, REG_A6XX_SP_CS_IBO_COUNT, 1);
347
 
   OUT_RING(ring, kernel->num_bufs);
348
 
 
349
 
   fd_ringbuffer_del(state);
350
 
}
351
 
 
352
 
static inline unsigned
353
 
event_write(struct fd_ringbuffer *ring, struct kernel *kernel,
354
 
            enum vgt_event_type evt, bool timestamp)
355
 
{
356
 
   unsigned seqno = 0;
357
 
 
358
 
   OUT_PKT7(ring, CP_EVENT_WRITE, timestamp ? 4 : 1);
359
 
   OUT_RING(ring, CP_EVENT_WRITE_0_EVENT(evt));
360
 
   if (timestamp) {
361
 
      struct ir3_kernel *ir3_kernel = to_ir3_kernel(kernel);
362
 
      struct a6xx_backend *a6xx_backend = to_a6xx_backend(ir3_kernel->backend);
363
 
      seqno = ++a6xx_backend->seqno;
364
 
      OUT_RELOC(ring, control_ptr(a6xx_backend, seqno)); /* ADDR_LO/HI */
365
 
      OUT_RING(ring, seqno);
366
 
   }
367
 
 
368
 
   return seqno;
369
 
}
370
 
 
371
 
static inline void
372
 
cache_flush(struct fd_ringbuffer *ring, struct kernel *kernel)
373
 
{
374
 
   struct ir3_kernel *ir3_kernel = to_ir3_kernel(kernel);
375
 
   struct a6xx_backend *a6xx_backend = to_a6xx_backend(ir3_kernel->backend);
376
 
   unsigned seqno;
377
 
 
378
 
   seqno = event_write(ring, kernel, RB_DONE_TS, true);
379
 
 
380
 
   OUT_PKT7(ring, CP_WAIT_REG_MEM, 6);
381
 
   OUT_RING(ring, CP_WAIT_REG_MEM_0_FUNCTION(WRITE_EQ) |
382
 
                     CP_WAIT_REG_MEM_0_POLL_MEMORY);
383
 
   OUT_RELOC(ring, control_ptr(a6xx_backend, seqno));
384
 
   OUT_RING(ring, CP_WAIT_REG_MEM_3_REF(seqno));
385
 
   OUT_RING(ring, CP_WAIT_REG_MEM_4_MASK(~0));
386
 
   OUT_RING(ring, CP_WAIT_REG_MEM_5_DELAY_LOOP_CYCLES(16));
387
 
 
388
 
   seqno = event_write(ring, kernel, CACHE_FLUSH_TS, true);
389
 
 
390
 
   OUT_PKT7(ring, CP_WAIT_MEM_GTE, 4);
391
 
   OUT_RING(ring, CP_WAIT_MEM_GTE_0_RESERVED(0));
392
 
   OUT_RELOC(ring, control_ptr(a6xx_backend, seqno));
393
 
   OUT_RING(ring, CP_WAIT_MEM_GTE_3_REF(seqno));
394
 
}
395
 
 
396
 
static void
397
 
a6xx_emit_grid(struct kernel *kernel, uint32_t grid[3],
398
 
               struct fd_submit *submit)
399
 
{
400
 
   struct ir3_kernel *ir3_kernel = to_ir3_kernel(kernel);
401
 
   struct a6xx_backend *a6xx_backend = to_a6xx_backend(ir3_kernel->backend);
402
 
   struct fd_ringbuffer *ring = fd_submit_new_ringbuffer(
403
 
      submit, 0, FD_RINGBUFFER_PRIMARY | FD_RINGBUFFER_GROWABLE);
404
 
 
405
 
   cs_program_emit(ring, kernel);
406
 
   cs_const_emit(ring, kernel, grid);
407
 
   cs_ibo_emit(ring, submit, kernel);
408
 
 
409
 
   OUT_PKT7(ring, CP_SET_MARKER, 1);
410
 
   OUT_RING(ring, A6XX_CP_SET_MARKER_0_MODE(RM6_COMPUTE));
411
 
 
412
 
   const unsigned *local_size = kernel->local_size;
413
 
   const unsigned *num_groups = grid;
414
 
 
415
 
   unsigned work_dim = 0;
416
 
   for (int i = 0; i < 3; i++) {
417
 
      if (!grid[i])
418
 
         break;
419
 
      work_dim++;
420
 
   }
421
 
 
422
 
   OUT_PKT4(ring, REG_A6XX_HLSQ_CS_NDRANGE_0, 7);
423
 
   OUT_RING(ring, A6XX_HLSQ_CS_NDRANGE_0_KERNELDIM(work_dim) |
424
 
                     A6XX_HLSQ_CS_NDRANGE_0_LOCALSIZEX(local_size[0] - 1) |
425
 
                     A6XX_HLSQ_CS_NDRANGE_0_LOCALSIZEY(local_size[1] - 1) |
426
 
                     A6XX_HLSQ_CS_NDRANGE_0_LOCALSIZEZ(local_size[2] - 1));
427
 
   OUT_RING(ring,
428
 
            A6XX_HLSQ_CS_NDRANGE_1_GLOBALSIZE_X(local_size[0] * num_groups[0]));
429
 
   OUT_RING(ring, 0); /* HLSQ_CS_NDRANGE_2_GLOBALOFF_X */
430
 
   OUT_RING(ring,
431
 
            A6XX_HLSQ_CS_NDRANGE_3_GLOBALSIZE_Y(local_size[1] * num_groups[1]));
432
 
   OUT_RING(ring, 0); /* HLSQ_CS_NDRANGE_4_GLOBALOFF_Y */
433
 
   OUT_RING(ring,
434
 
            A6XX_HLSQ_CS_NDRANGE_5_GLOBALSIZE_Z(local_size[2] * num_groups[2]));
435
 
   OUT_RING(ring, 0); /* HLSQ_CS_NDRANGE_6_GLOBALOFF_Z */
436
 
 
437
 
   OUT_PKT4(ring, REG_A6XX_HLSQ_CS_KERNEL_GROUP_X, 3);
438
 
   OUT_RING(ring, 1); /* HLSQ_CS_KERNEL_GROUP_X */
439
 
   OUT_RING(ring, 1); /* HLSQ_CS_KERNEL_GROUP_Y */
440
 
   OUT_RING(ring, 1); /* HLSQ_CS_KERNEL_GROUP_Z */
441
 
 
442
 
   if (a6xx_backend->num_perfcntrs > 0) {
443
 
      a6xx_backend->query_mem = fd_bo_new(
444
 
         a6xx_backend->dev,
445
 
         a6xx_backend->num_perfcntrs * sizeof(struct fd6_query_sample), 0, "query");
446
 
 
447
 
      /* configure the performance counters to count the requested
448
 
       * countables:
449
 
       */
450
 
      for (unsigned i = 0; i < a6xx_backend->num_perfcntrs; i++) {
451
 
         const struct perfcntr *counter = &a6xx_backend->perfcntrs[i];
452
 
 
453
 
         OUT_PKT4(ring, counter->select_reg, 1);
454
 
         OUT_RING(ring, counter->selector);
455
 
      }
456
 
 
457
 
      OUT_PKT7(ring, CP_WAIT_FOR_IDLE, 0);
458
 
 
459
 
      /* and snapshot the start values: */
460
 
      for (unsigned i = 0; i < a6xx_backend->num_perfcntrs; i++) {
461
 
         const struct perfcntr *counter = &a6xx_backend->perfcntrs[i];
462
 
 
463
 
         OUT_PKT7(ring, CP_REG_TO_MEM, 3);
464
 
         OUT_RING(ring, CP_REG_TO_MEM_0_64B |
465
 
                           CP_REG_TO_MEM_0_REG(counter->counter_reg_lo));
466
 
         OUT_RELOC(ring, query_sample_idx(a6xx_backend, i, start));
467
 
      }
468
 
   }
469
 
 
470
 
   OUT_PKT7(ring, CP_EXEC_CS, 4);
471
 
   OUT_RING(ring, 0x00000000);
472
 
   OUT_RING(ring, CP_EXEC_CS_1_NGROUPS_X(grid[0]));
473
 
   OUT_RING(ring, CP_EXEC_CS_2_NGROUPS_Y(grid[1]));
474
 
   OUT_RING(ring, CP_EXEC_CS_3_NGROUPS_Z(grid[2]));
475
 
 
476
 
   OUT_PKT7(ring, CP_WAIT_FOR_IDLE, 0);
477
 
 
478
 
   if (a6xx_backend->num_perfcntrs > 0) {
479
 
      /* snapshot the end values: */
480
 
      for (unsigned i = 0; i < a6xx_backend->num_perfcntrs; i++) {
481
 
         const struct perfcntr *counter = &a6xx_backend->perfcntrs[i];
482
 
 
483
 
         OUT_PKT7(ring, CP_REG_TO_MEM, 3);
484
 
         OUT_RING(ring, CP_REG_TO_MEM_0_64B |
485
 
                           CP_REG_TO_MEM_0_REG(counter->counter_reg_lo));
486
 
         OUT_RELOC(ring, query_sample_idx(a6xx_backend, i, stop));
487
 
      }
488
 
 
489
 
      /* and compute the result: */
490
 
      for (unsigned i = 0; i < a6xx_backend->num_perfcntrs; i++) {
491
 
         /* result += stop - start: */
492
 
         OUT_PKT7(ring, CP_MEM_TO_MEM, 9);
493
 
         OUT_RING(ring, CP_MEM_TO_MEM_0_DOUBLE | CP_MEM_TO_MEM_0_NEG_C);
494
 
         OUT_RELOC(ring, query_sample_idx(a6xx_backend, i, result)); /* dst */
495
 
         OUT_RELOC(ring, query_sample_idx(a6xx_backend, i, result)); /* srcA */
496
 
         OUT_RELOC(ring, query_sample_idx(a6xx_backend, i, stop));   /* srcB */
497
 
         OUT_RELOC(ring, query_sample_idx(a6xx_backend, i, start));  /* srcC */
498
 
      }
499
 
   }
500
 
 
501
 
   cache_flush(ring, kernel);
502
 
}
503
 
 
504
 
static void
505
 
a6xx_set_perfcntrs(struct backend *b, const struct perfcntr *perfcntrs,
506
 
                   unsigned num_perfcntrs)
507
 
{
508
 
   struct a6xx_backend *a6xx_backend = to_a6xx_backend(b);
509
 
 
510
 
   a6xx_backend->perfcntrs = perfcntrs;
511
 
   a6xx_backend->num_perfcntrs = num_perfcntrs;
512
 
}
513
 
 
514
 
static void
515
 
a6xx_read_perfcntrs(struct backend *b, uint64_t *results)
516
 
{
517
 
   struct a6xx_backend *a6xx_backend = to_a6xx_backend(b);
518
 
 
519
 
   fd_bo_cpu_prep(a6xx_backend->query_mem, NULL, FD_BO_PREP_READ);
520
 
   struct fd6_query_sample *samples = fd_bo_map(a6xx_backend->query_mem);
521
 
 
522
 
   for (unsigned i = 0; i < a6xx_backend->num_perfcntrs; i++) {
523
 
      results[i] = samples[i].result;
524
 
   }
525
 
}
526
 
 
527
 
struct backend *
528
 
a6xx_init(struct fd_device *dev, const struct fd_dev_id *dev_id)
529
 
{
530
 
   struct a6xx_backend *a6xx_backend = calloc(1, sizeof(*a6xx_backend));
531
 
 
532
 
   a6xx_backend->base = (struct backend){
533
 
      .assemble = a6xx_assemble,
534
 
      .disassemble = a6xx_disassemble,
535
 
      .emit_grid = a6xx_emit_grid,
536
 
      .set_perfcntrs = a6xx_set_perfcntrs,
537
 
      .read_perfcntrs = a6xx_read_perfcntrs,
538
 
   };
539
 
 
540
 
   a6xx_backend->compiler = ir3_compiler_create(dev, dev_id,
541
 
                                                &(struct ir3_compiler_options){});
542
 
   a6xx_backend->dev = dev;
543
 
 
544
 
   a6xx_backend->info = fd_dev_info(dev_id);
545
 
 
546
 
   a6xx_backend->control_mem =
547
 
      fd_bo_new(dev, 0x1000, 0, "control");
548
 
 
549
 
   return &a6xx_backend->base;
550
 
}