• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2010 Red Hat Inc.
3  * Copyright © 2014-2017 Broadcom
4  * Copyright (C) 2019-2020 Collabora, Ltd.
5  * Copyright 2006 VMware, Inc.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * on the rights to use, copy, modify, merge, publish, distribute, sub
11  * license, and/or sell copies of the Software, and to permit persons to whom
12  * the Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the next
15  * paragraph) shall be included in all copies or substantial portions of the
16  * Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24  * USE OR OTHER DEALINGS IN THE SOFTWARE.
25  */
26 #include <stdio.h>
27 #include <errno.h>
28 #include "pipe/p_defines.h"
29 #include "pipe/p_state.h"
30 #include "pipe/p_context.h"
31 #include "pipe/p_screen.h"
32 #include "util/u_memory.h"
33 #include "util/u_screen.h"
34 #include "util/u_inlines.h"
35 #include "util/format/u_format.h"
36 #include "util/u_upload_mgr.h"
37 #include "util/half_float.h"
38 #include "frontend/winsys_handle.h"
39 #include "frontend/sw_winsys.h"
40 #include "gallium/auxiliary/util/u_transfer.h"
41 #include "gallium/auxiliary/util/u_surface.h"
42 #include "gallium/auxiliary/util/u_framebuffer.h"
43 #include "agx_public.h"
44 #include "agx_state.h"
45 #include "magic.h"
46 #include "asahi/compiler/agx_compile.h"
47 #include "asahi/lib/decode.h"
48 #include "asahi/lib/tiling.h"
49 #include "asahi/lib/agx_formats.h"
50 
51 static const struct debug_named_value agx_debug_options[] = {
52    {"trace",     AGX_DBG_TRACE,    "Trace the command stream"},
53    {"deqp",      AGX_DBG_DEQP,     "Hacks for dEQP"},
54    {"no16",      AGX_DBG_NO16,     "Disable 16-bit support"},
55    DEBUG_NAMED_VALUE_END
56 };
57 
58 void agx_init_state_functions(struct pipe_context *ctx);
59 
60 static struct pipe_query *
agx_create_query(struct pipe_context * ctx,unsigned query_type,unsigned index)61 agx_create_query(struct pipe_context *ctx, unsigned query_type, unsigned index)
62 {
63    struct agx_query *query = CALLOC_STRUCT(agx_query);
64 
65    return (struct pipe_query *)query;
66 }
67 
68 static void
agx_destroy_query(struct pipe_context * ctx,struct pipe_query * query)69 agx_destroy_query(struct pipe_context *ctx, struct pipe_query *query)
70 {
71    FREE(query);
72 }
73 
74 static bool
agx_begin_query(struct pipe_context * ctx,struct pipe_query * query)75 agx_begin_query(struct pipe_context *ctx, struct pipe_query *query)
76 {
77    return true;
78 }
79 
80 static bool
agx_end_query(struct pipe_context * ctx,struct pipe_query * query)81 agx_end_query(struct pipe_context *ctx, struct pipe_query *query)
82 {
83    return true;
84 }
85 
86 static bool
agx_get_query_result(struct pipe_context * ctx,struct pipe_query * query,bool wait,union pipe_query_result * vresult)87 agx_get_query_result(struct pipe_context *ctx,
88                      struct pipe_query *query,
89                      bool wait,
90                      union pipe_query_result *vresult)
91 {
92    uint64_t *result = (uint64_t*)vresult;
93 
94    *result = 0;
95    return true;
96 }
97 
98 static void
agx_set_active_query_state(struct pipe_context * pipe,bool enable)99 agx_set_active_query_state(struct pipe_context *pipe, bool enable)
100 {
101 }
102 
103 
104 /*
105  * resource
106  */
107 
108 static struct pipe_resource *
agx_resource_from_handle(struct pipe_screen * pscreen,const struct pipe_resource * templat,struct winsys_handle * whandle,unsigned usage)109 agx_resource_from_handle(struct pipe_screen *pscreen,
110                          const struct pipe_resource *templat,
111                          struct winsys_handle *whandle,
112                          unsigned usage)
113 {
114    unreachable("Imports todo");
115 }
116 
117 static bool
agx_resource_get_handle(struct pipe_screen * pscreen,struct pipe_context * ctx,struct pipe_resource * pt,struct winsys_handle * handle,unsigned usage)118 agx_resource_get_handle(struct pipe_screen *pscreen,
119                         struct pipe_context *ctx,
120                         struct pipe_resource *pt,
121                         struct winsys_handle *handle,
122                         unsigned usage)
123 {
124    unreachable("Handles todo");
125 }
126 
127 static inline bool
agx_is_2d(const struct agx_resource * pres)128 agx_is_2d(const struct agx_resource *pres)
129 {
130    switch (pres->base.target) {
131    case PIPE_TEXTURE_2D:
132    case PIPE_TEXTURE_RECT:
133    case PIPE_TEXTURE_CUBE:
134       return true;
135    default:
136       return false;
137    }
138 }
139 
140 static bool
agx_must_tile(const struct agx_resource * pres)141 agx_must_tile(const struct agx_resource *pres)
142 {
143    switch (pres->base.target) {
144    case PIPE_TEXTURE_CUBE:
145    case PIPE_TEXTURE_3D:
146       /* We don't know how to do linear for these */
147       return true;
148    default:
149       break;
150    }
151 
152    return false;
153 }
154 
155 static bool
agx_should_tile(const struct agx_resource * pres)156 agx_should_tile(const struct agx_resource *pres)
157 {
158    const unsigned valid_binding =
159       PIPE_BIND_DEPTH_STENCIL |
160       PIPE_BIND_RENDER_TARGET |
161       PIPE_BIND_BLENDABLE |
162       PIPE_BIND_SAMPLER_VIEW |
163       PIPE_BIND_DISPLAY_TARGET |
164       PIPE_BIND_SCANOUT |
165       PIPE_BIND_SHARED;
166 
167    unsigned bpp = util_format_get_blocksizebits(pres->base.format);
168 
169    bool can_tile = agx_is_2d(pres)
170       && (bpp == 32)
171       && ((pres->base.bind & ~valid_binding) == 0);
172 
173    bool should_tile = (pres->base.usage != PIPE_USAGE_STREAM);
174    bool must_tile = agx_must_tile(pres);
175 
176    assert(!(must_tile && !can_tile));
177    return must_tile || (can_tile && should_tile);
178 }
179 
180 static struct pipe_resource *
agx_resource_create(struct pipe_screen * screen,const struct pipe_resource * templ)181 agx_resource_create(struct pipe_screen *screen,
182                     const struct pipe_resource *templ)
183 {
184    struct agx_device *dev = agx_device(screen);
185    struct agx_resource *nresource;
186 
187    nresource = CALLOC_STRUCT(agx_resource);
188    if (!nresource)
189       return NULL;
190 
191    nresource->base = *templ;
192    nresource->base.screen = screen;
193 
194    nresource->modifier = agx_should_tile(nresource) ?
195       DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER : DRM_FORMAT_MOD_LINEAR;
196 
197    unsigned offset = 0;
198 
199    for (unsigned l = 0; l <= templ->last_level; ++l) {
200       unsigned width = u_minify(templ->width0, l);
201       unsigned height = u_minify(templ->height0, l);
202 
203       if (nresource->modifier == DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER) {
204          width = ALIGN_POT(width, 64);
205          height = ALIGN_POT(height, 64);
206       }
207 
208       nresource->slices[l].line_stride =
209          util_format_get_stride(templ->format, width);
210 
211       nresource->slices[l].offset = offset;
212       offset += ALIGN_POT(nresource->slices[l].line_stride * height, 0x80);
213    }
214 
215    /* Arrays and cubemaps have the entire miptree duplicated */
216    nresource->array_stride = ALIGN_POT(offset, 64);
217    unsigned size = ALIGN_POT(nresource->array_stride * templ->array_size, 4096);
218 
219    pipe_reference_init(&nresource->base.reference, 1);
220 
221    struct sw_winsys *winsys = ((struct agx_screen *) screen)->winsys;
222 
223    if (templ->bind & (PIPE_BIND_DISPLAY_TARGET |
224                       PIPE_BIND_SCANOUT |
225                       PIPE_BIND_SHARED)) {
226       unsigned width0 = templ->width0, height0 = templ->height0;
227 
228       if (nresource->modifier == DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER) {
229          width0 = ALIGN_POT(width0, 64);
230          height0 = ALIGN_POT(height0, 64);
231       }
232 
233       nresource->dt = winsys->displaytarget_create(winsys,
234                       templ->bind,
235                       templ->format,
236                       width0,
237                       height0,
238                       64,
239                       NULL /*map_front_private*/,
240                       &nresource->dt_stride);
241 
242       nresource->slices[0].line_stride = nresource->dt_stride;
243       assert((nresource->dt_stride & 0xF) == 0);
244 
245       offset = nresource->slices[0].line_stride * ALIGN_POT(templ->height0, 64);
246 
247       if (nresource->dt == NULL) {
248          FREE(nresource);
249          return NULL;
250       }
251    }
252 
253    nresource->bo = agx_bo_create(dev, size, AGX_MEMORY_TYPE_FRAMEBUFFER);
254 
255    if (!nresource->bo) {
256       FREE(nresource);
257       return NULL;
258    }
259 
260    return &nresource->base;
261 }
262 
263 static uint8_t *
agx_rsrc_offset(struct agx_resource * rsrc,unsigned level,unsigned z)264 agx_rsrc_offset(struct agx_resource *rsrc, unsigned level, unsigned z)
265 {
266    struct agx_bo *bo = rsrc->bo;
267    uint8_t *map = ((uint8_t *) bo->ptr.cpu) + rsrc->slices[level].offset;
268    map += z * rsrc->array_stride;
269 
270    return map;
271 }
272 
273 static void
agx_resource_destroy(struct pipe_screen * screen,struct pipe_resource * prsrc)274 agx_resource_destroy(struct pipe_screen *screen,
275                      struct pipe_resource *prsrc)
276 {
277    struct agx_resource *rsrc = (struct agx_resource *)prsrc;
278 
279    if (rsrc->dt) {
280       /* display target */
281       struct agx_screen *agx_screen = (struct agx_screen*)screen;
282       struct sw_winsys *winsys = agx_screen->winsys;
283       winsys->displaytarget_destroy(winsys, rsrc->dt);
284    }
285 
286    agx_bo_unreference(rsrc->bo);
287    FREE(rsrc);
288 }
289 
290 
291 /*
292  * transfer
293  */
294 
295 static void
agx_transfer_flush_region(struct pipe_context * pipe,struct pipe_transfer * transfer,const struct pipe_box * box)296 agx_transfer_flush_region(struct pipe_context *pipe,
297                           struct pipe_transfer *transfer,
298                           const struct pipe_box *box)
299 {
300 }
301 
302 static void *
agx_transfer_map(struct pipe_context * pctx,struct pipe_resource * resource,unsigned level,unsigned usage,const struct pipe_box * box,struct pipe_transfer ** out_transfer)303 agx_transfer_map(struct pipe_context *pctx,
304                  struct pipe_resource *resource,
305                  unsigned level,
306                  unsigned usage,  /* a combination of PIPE_MAP_x */
307                  const struct pipe_box *box,
308                  struct pipe_transfer **out_transfer)
309 {
310    struct agx_context *ctx = agx_context(pctx);
311    struct agx_resource *rsrc = agx_resource(resource);
312    unsigned bytes_per_pixel = util_format_get_blocksize(resource->format);
313 
314    /* Can't map tiled/compressed directly */
315    if ((usage & PIPE_MAP_DIRECTLY) && rsrc->modifier != DRM_FORMAT_MOD_LINEAR)
316       return NULL;
317 
318    if (ctx->batch->cbufs[0] && resource == ctx->batch->cbufs[0]->texture)
319       pctx->flush(pctx, NULL, 0);
320    if (ctx->batch->zsbuf && resource == ctx->batch->zsbuf->texture)
321       pctx->flush(pctx, NULL, 0);
322 
323    struct agx_transfer *transfer = CALLOC_STRUCT(agx_transfer);
324    transfer->base.level = level;
325    transfer->base.usage = usage;
326    transfer->base.box = *box;
327 
328    pipe_resource_reference(&transfer->base.resource, resource);
329    *out_transfer = &transfer->base;
330 
331    if (rsrc->modifier == DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER) {
332       transfer->base.stride = box->width * bytes_per_pixel;
333       transfer->base.layer_stride = transfer->base.stride * box->height;
334       transfer->map = calloc(transfer->base.layer_stride, box->depth);
335       assert(box->depth == 1);
336 
337       if ((usage & PIPE_MAP_READ) && BITSET_TEST(rsrc->data_valid, level)) {
338          for (unsigned z = 0; z < box->depth; ++z) {
339             uint8_t *map = agx_rsrc_offset(rsrc, level, box->z + z);
340 
341             agx_detile(map, transfer->map,
342                u_minify(resource->width0, level), bytes_per_pixel * 8,
343                transfer->base.stride / bytes_per_pixel,
344                box->x, box->y, box->x + box->width, box->y + box->height);
345          }
346       }
347 
348       return transfer->map;
349    } else {
350       assert (rsrc->modifier == DRM_FORMAT_MOD_LINEAR);
351 
352       transfer->base.stride = rsrc->slices[level].line_stride;
353       transfer->base.layer_stride = rsrc->array_stride;
354 
355       /* Be conservative for direct writes */
356 
357       if ((usage & PIPE_MAP_WRITE) && (usage & PIPE_MAP_DIRECTLY))
358          BITSET_SET(rsrc->data_valid, level);
359 
360       return agx_rsrc_offset(rsrc, level, box->z)
361              + transfer->base.box.y * rsrc->slices[level].line_stride
362              + transfer->base.box.x * bytes_per_pixel;
363    }
364 }
365 
366 static void
agx_transfer_unmap(struct pipe_context * pctx,struct pipe_transfer * transfer)367 agx_transfer_unmap(struct pipe_context *pctx,
368                    struct pipe_transfer *transfer)
369 {
370    /* Gallium expects writeback here, so we tile */
371 
372    struct agx_transfer *trans = agx_transfer(transfer);
373    struct pipe_resource *prsrc = transfer->resource;
374    struct agx_resource *rsrc = (struct agx_resource *) prsrc;
375    unsigned bytes_per_pixel = util_format_get_blocksize(prsrc->format);
376 
377    if (transfer->usage & PIPE_MAP_WRITE)
378       BITSET_SET(rsrc->data_valid, transfer->level);
379 
380    /* Tiling will occur in software from a staging cpu buffer */
381    if ((transfer->usage & PIPE_MAP_WRITE) &&
382          rsrc->modifier == DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER) {
383       assert(trans->map != NULL);
384 
385       for (unsigned z = 0; z < transfer->box.depth; ++z) {
386          uint8_t *map = agx_rsrc_offset(rsrc, transfer->level,
387                transfer->box.z + z);
388 
389          agx_tile(map, trans->map,
390             u_minify(transfer->resource->width0, transfer->level),
391             bytes_per_pixel * 8,
392             transfer->stride / bytes_per_pixel,
393             transfer->box.x, transfer->box.y,
394             transfer->box.x + transfer->box.width,
395             transfer->box.y + transfer->box.height);
396       }
397    }
398 
399    /* Free the transfer */
400    free(trans->map);
401    pipe_resource_reference(&transfer->resource, NULL);
402    FREE(transfer);
403 }
404 
405 /*
406  * clear/copy
407  */
408 static void
agx_clear(struct pipe_context * pctx,unsigned buffers,const struct pipe_scissor_state * scissor_state,const union pipe_color_union * color,double depth,unsigned stencil)409 agx_clear(struct pipe_context *pctx, unsigned buffers, const struct pipe_scissor_state *scissor_state,
410           const union pipe_color_union *color, double depth, unsigned stencil)
411 {
412    struct agx_context *ctx = agx_context(pctx);
413    ctx->batch->clear |= buffers;
414    memcpy(ctx->batch->clear_color, color->f, sizeof(color->f));
415 }
416 
417 
418 static void
agx_flush_resource(struct pipe_context * ctx,struct pipe_resource * resource)419 agx_flush_resource(struct pipe_context *ctx,
420                    struct pipe_resource *resource)
421 {
422 }
423 
424 /*
425  * context
426  */
427 static void
agx_flush(struct pipe_context * pctx,struct pipe_fence_handle ** fence,unsigned flags)428 agx_flush(struct pipe_context *pctx,
429           struct pipe_fence_handle **fence,
430           unsigned flags)
431 {
432    struct agx_context *ctx = agx_context(pctx);
433 
434    if (fence)
435       *fence = NULL;
436 
437    /* TODO */
438    if (!ctx->batch->cbufs[0])
439       return;
440 
441    /* Nothing to do */
442    if (!(ctx->batch->draw | ctx->batch->clear))
443       return;
444 
445    /* Finalize the encoder */
446    uint8_t stop[5 + 64] = { 0x00, 0x00, 0x00, 0xc0, 0x00 };
447    memcpy(ctx->batch->encoder_current, stop, sizeof(stop));
448 
449    /* Emit the commandbuffer */
450    uint64_t pipeline_clear = 0;
451    bool clear_pipeline_textures = false;
452 
453    struct agx_device *dev = agx_device(pctx->screen);
454 
455    if (ctx->batch->clear & PIPE_CLEAR_COLOR0) {
456       uint16_t clear_colour[4] = {
457          _mesa_float_to_half(ctx->batch->clear_color[0]),
458          _mesa_float_to_half(ctx->batch->clear_color[1]),
459          _mesa_float_to_half(ctx->batch->clear_color[2]),
460          _mesa_float_to_half(ctx->batch->clear_color[3])
461       };
462 
463 
464       pipeline_clear = agx_build_clear_pipeline(ctx,
465                                dev->internal.clear,
466                                agx_pool_upload(&ctx->batch->pool, clear_colour, sizeof(clear_colour)));
467    } else {
468       enum pipe_format fmt = ctx->batch->cbufs[0]->format;
469       enum agx_format internal = agx_pixel_format[fmt].internal;
470       uint32_t shader = dev->reload.format[internal];
471 
472       pipeline_clear = agx_build_reload_pipeline(ctx, shader,
473                                ctx->batch->cbufs[0]);
474 
475       clear_pipeline_textures = true;
476    }
477 
478    uint64_t pipeline_store =
479       agx_build_store_pipeline(ctx,
480                                dev->internal.store,
481                                agx_pool_upload(&ctx->batch->pool, ctx->render_target[0], sizeof(ctx->render_target)));
482 
483    /* Pipelines must 64 aligned */
484    struct agx_ptr pipeline_null =
485       agx_pool_alloc_aligned(&ctx->batch->pipeline_pool, 64, 64);
486    memset(pipeline_null.cpu, 0, 64);
487 
488    struct agx_resource *rt0 = agx_resource(ctx->batch->cbufs[0]->texture);
489    BITSET_SET(rt0->data_valid, 0);
490 
491    struct agx_resource *zbuf = ctx->batch->zsbuf ?
492       agx_resource(ctx->batch->zsbuf->texture) : NULL;
493 
494    if (zbuf)
495       BITSET_SET(zbuf->data_valid, 0);
496 
497    /* BO list for a given batch consists of:
498     *  - BOs for the batch's framebuffer surfaces
499     *  - BOs for the batch's pools
500     *  - BOs for the encoder
501     *  - BO for internal shaders
502     *  - BOs added to the batch explicitly
503     */
504    struct agx_batch *batch = ctx->batch;
505 
506    agx_batch_add_bo(batch, batch->encoder);
507    agx_batch_add_bo(batch, batch->scissor.bo);
508    agx_batch_add_bo(batch, dev->internal.bo);
509    agx_batch_add_bo(batch, dev->reload.bo);
510 
511    for (unsigned i = 0; i < batch->nr_cbufs; ++i) {
512       struct pipe_surface *surf = batch->cbufs[i];
513       assert(surf != NULL && surf->texture != NULL);
514       struct agx_resource *rsrc = agx_resource(surf->texture);
515       agx_batch_add_bo(batch, rsrc->bo);
516    }
517 
518    if (batch->zsbuf) {
519       struct pipe_surface *surf = batch->zsbuf;
520       struct agx_resource *rsrc = agx_resource(surf->texture);
521       agx_batch_add_bo(batch, rsrc->bo);
522    }
523 
524    unsigned handle_count =
525       BITSET_COUNT(batch->bo_list) +
526       agx_pool_num_bos(&batch->pool) +
527       agx_pool_num_bos(&batch->pipeline_pool);
528 
529    uint32_t *handles = calloc(sizeof(uint32_t), handle_count);
530    unsigned handle = 0, handle_i = 0;
531 
532    BITSET_FOREACH_SET(handle, batch->bo_list, sizeof(batch->bo_list) * 8) {
533       handles[handle_i++] = handle;
534    }
535 
536    agx_pool_get_bo_handles(&batch->pool, handles + handle_i);
537    handle_i += agx_pool_num_bos(&batch->pool);
538 
539    agx_pool_get_bo_handles(&batch->pipeline_pool, handles + handle_i);
540    handle_i += agx_pool_num_bos(&batch->pipeline_pool);
541 
542    /* Size calculation should've been exact */
543    assert(handle_i == handle_count);
544 
545    unsigned cmdbuf_id = agx_get_global_id(dev);
546    unsigned encoder_id = agx_get_global_id(dev);
547 
548    unsigned cmdbuf_size = demo_cmdbuf(dev->cmdbuf.ptr.cpu,
549                dev->cmdbuf.size,
550                &ctx->batch->pool,
551                ctx->batch->encoder->ptr.gpu,
552                encoder_id,
553                ctx->batch->scissor.bo->ptr.gpu,
554                ctx->batch->width,
555                ctx->batch->height,
556                pipeline_null.gpu,
557                pipeline_clear,
558                pipeline_store,
559                rt0->bo->ptr.gpu,
560                clear_pipeline_textures);
561 
562    /* Generate the mapping table from the BO list */
563    demo_mem_map(dev->memmap.ptr.cpu, dev->memmap.size, handles, handle_count,
564                 cmdbuf_id, encoder_id, cmdbuf_size);
565 
566    free(handles);
567 
568    agx_submit_cmdbuf(dev, dev->cmdbuf.handle, dev->memmap.handle, dev->queue.id);
569 
570    agx_wait_queue(dev->queue);
571 
572    if (dev->debug & AGX_DBG_TRACE) {
573       agxdecode_cmdstream(dev->cmdbuf.handle, dev->memmap.handle, true);
574       agxdecode_next_frame();
575    }
576 
577    memset(batch->bo_list, 0, sizeof(batch->bo_list));
578    agx_pool_cleanup(&ctx->batch->pool);
579    agx_pool_cleanup(&ctx->batch->pipeline_pool);
580    agx_pool_init(&ctx->batch->pool, dev, AGX_MEMORY_TYPE_FRAMEBUFFER, true);
581    agx_pool_init(&ctx->batch->pipeline_pool, dev, AGX_MEMORY_TYPE_CMDBUF_32, true);
582    ctx->batch->clear = 0;
583    ctx->batch->draw = 0;
584    ctx->batch->encoder_current = ctx->batch->encoder->ptr.cpu;
585    ctx->batch->scissor.count = 0;
586    ctx->dirty = ~0;
587 }
588 
589 static void
agx_destroy_context(struct pipe_context * pctx)590 agx_destroy_context(struct pipe_context *pctx)
591 {
592    struct agx_context *ctx = agx_context(pctx);
593 
594    if (pctx->stream_uploader)
595       u_upload_destroy(pctx->stream_uploader);
596 
597    if (ctx->blitter)
598       util_blitter_destroy(ctx->blitter);
599 
600    util_unreference_framebuffer_state(&ctx->framebuffer);
601 
602    FREE(ctx);
603 }
604 
605 static void
agx_invalidate_resource(struct pipe_context * ctx,struct pipe_resource * resource)606 agx_invalidate_resource(struct pipe_context *ctx,
607                         struct pipe_resource *resource)
608 {
609 }
610 
611 static struct pipe_context *
agx_create_context(struct pipe_screen * screen,void * priv,unsigned flags)612 agx_create_context(struct pipe_screen *screen,
613                    void *priv, unsigned flags)
614 {
615    struct agx_context *ctx = CALLOC_STRUCT(agx_context);
616    struct pipe_context *pctx = &ctx->base;
617 
618    if (!ctx)
619       return NULL;
620 
621    pctx->screen = screen;
622    pctx->priv = priv;
623 
624    ctx->batch = CALLOC_STRUCT(agx_batch);
625    agx_pool_init(&ctx->batch->pool,
626                  agx_device(screen), AGX_MEMORY_TYPE_FRAMEBUFFER, true);
627    agx_pool_init(&ctx->batch->pipeline_pool,
628                  agx_device(screen), AGX_MEMORY_TYPE_SHADER, true);
629    ctx->batch->encoder = agx_bo_create(agx_device(screen), 0x80000, AGX_MEMORY_TYPE_FRAMEBUFFER);
630    ctx->batch->encoder_current = ctx->batch->encoder->ptr.cpu;
631    ctx->batch->scissor.bo = agx_bo_create(agx_device(screen), 0x80000, AGX_MEMORY_TYPE_FRAMEBUFFER);
632 
633    /* Upload fixed shaders (TODO: compile them?) */
634 
635    pctx->stream_uploader = u_upload_create_default(pctx);
636    if (!pctx->stream_uploader) {
637       FREE(pctx);
638       return NULL;
639    }
640    pctx->const_uploader = pctx->stream_uploader;
641 
642    pctx->destroy = agx_destroy_context;
643    pctx->flush = agx_flush;
644    pctx->clear = agx_clear;
645    pctx->resource_copy_region = util_resource_copy_region;
646    pctx->blit = agx_blit;
647    pctx->flush_resource = agx_flush_resource;
648    pctx->create_query = agx_create_query;
649    pctx->destroy_query = agx_destroy_query;
650    pctx->begin_query = agx_begin_query;
651    pctx->end_query = agx_end_query;
652    pctx->get_query_result = agx_get_query_result;
653    pctx->set_active_query_state = agx_set_active_query_state;
654    pctx->buffer_map = agx_transfer_map;
655    pctx->texture_map = agx_transfer_map;
656    pctx->transfer_flush_region = agx_transfer_flush_region;
657    pctx->buffer_unmap = agx_transfer_unmap;
658    pctx->texture_unmap = agx_transfer_unmap;
659    pctx->buffer_subdata = u_default_buffer_subdata;
660    pctx->texture_subdata = u_default_texture_subdata;
661    pctx->invalidate_resource = agx_invalidate_resource;
662    agx_init_state_functions(pctx);
663 
664 
665    ctx->blitter = util_blitter_create(pctx);
666 
667    return pctx;
668 }
669 
670 static void
agx_flush_frontbuffer(struct pipe_screen * _screen,struct pipe_context * pctx,struct pipe_resource * prsrc,unsigned level,unsigned layer,void * context_private,struct pipe_box * box)671 agx_flush_frontbuffer(struct pipe_screen *_screen,
672                       struct pipe_context *pctx,
673                       struct pipe_resource *prsrc,
674                       unsigned level, unsigned layer,
675                       void *context_private, struct pipe_box *box)
676 {
677    struct agx_resource *rsrc = (struct agx_resource *) prsrc;
678    struct agx_screen *agx_screen = (struct agx_screen*)_screen;
679    struct sw_winsys *winsys = agx_screen->winsys;
680 
681    /* Dump the framebuffer */
682    assert (rsrc->dt);
683    void *map = winsys->displaytarget_map(winsys, rsrc->dt, PIPE_USAGE_DEFAULT);
684    assert(map != NULL);
685 
686    if (rsrc->modifier == DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER) {
687       agx_detile(rsrc->bo->ptr.cpu, map,
688                  rsrc->base.width0, 32, rsrc->dt_stride / 4,
689                  0, 0, rsrc->base.width0, rsrc->base.height0);
690    } else {
691       memcpy(map, rsrc->bo->ptr.cpu, rsrc->dt_stride * rsrc->base.height0);
692    }
693 
694    winsys->displaytarget_display(winsys, rsrc->dt, context_private, box);
695 }
696 
697 static const char *
agx_get_vendor(struct pipe_screen * pscreen)698 agx_get_vendor(struct pipe_screen* pscreen)
699 {
700    return "Asahi";
701 }
702 
703 static const char *
agx_get_device_vendor(struct pipe_screen * pscreen)704 agx_get_device_vendor(struct pipe_screen* pscreen)
705 {
706    return "Apple";
707 }
708 
709 static const char *
agx_get_name(struct pipe_screen * pscreen)710 agx_get_name(struct pipe_screen* pscreen)
711 {
712    return "Apple M1 (G13G B0)";
713 }
714 
715 static int
agx_get_param(struct pipe_screen * pscreen,enum pipe_cap param)716 agx_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
717 {
718    bool is_deqp = agx_device(pscreen)->debug & AGX_DBG_DEQP;
719 
720    switch (param) {
721    case PIPE_CAP_NPOT_TEXTURES:
722    case PIPE_CAP_MIXED_COLOR_DEPTH_BITS:
723    case PIPE_CAP_FRAGMENT_SHADER_TEXTURE_LOD:
724    case PIPE_CAP_VERTEX_SHADER_SATURATE:
725    case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
726    case PIPE_CAP_DEPTH_CLIP_DISABLE:
727    case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:
728    case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES:
729    case PIPE_CAP_FRAGMENT_SHADER_DERIVATIVES:
730    case PIPE_CAP_FRAMEBUFFER_NO_ATTACHMENT:
731    case PIPE_CAP_CLIP_HALFZ:
732       return 1;
733 
734    case PIPE_CAP_MAX_RENDER_TARGETS:
735       return 1;
736 
737    case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
738       return 0;
739 
740    case PIPE_CAP_OCCLUSION_QUERY:
741    case PIPE_CAP_PRIMITIVE_RESTART:
742    case PIPE_CAP_PRIMITIVE_RESTART_FIXED_INDEX:
743       return true;
744 
745    case PIPE_CAP_SAMPLER_VIEW_TARGET:
746    case PIPE_CAP_TEXTURE_SWIZZLE:
747    case PIPE_CAP_BLEND_EQUATION_SEPARATE:
748    case PIPE_CAP_INDEP_BLEND_ENABLE:
749    case PIPE_CAP_INDEP_BLEND_FUNC:
750    case PIPE_CAP_ACCELERATED:
751    case PIPE_CAP_UMA:
752    case PIPE_CAP_TEXTURE_FLOAT_LINEAR:
753    case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR:
754    case PIPE_CAP_TGSI_ARRAY_COMPONENTS:
755    case PIPE_CAP_CS_DERIVED_SYSTEM_VALUES_SUPPORTED:
756    case PIPE_CAP_PACKED_UNIFORMS:
757       return 1;
758 
759    case PIPE_CAP_TGSI_INSTANCEID:
760    case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR:
761    case PIPE_CAP_TEXTURE_MULTISAMPLE:
762    case PIPE_CAP_SURFACE_SAMPLE_COUNT:
763       return is_deqp;
764 
765    case PIPE_CAP_COPY_BETWEEN_COMPRESSED_AND_PLAIN_FORMATS:
766       return 0;
767 
768    case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:
769       return is_deqp ? PIPE_MAX_SO_BUFFERS : 0;
770 
771    case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS:
772    case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:
773       return is_deqp ? PIPE_MAX_SO_OUTPUTS : 0;
774 
775    case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
776    case PIPE_CAP_STREAM_OUTPUT_INTERLEAVE_BUFFERS:
777       return is_deqp ? 1 : 0;
778 
779    case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
780       return is_deqp ? 256 : 0;
781 
782    case PIPE_CAP_GLSL_FEATURE_LEVEL:
783    case PIPE_CAP_GLSL_FEATURE_LEVEL_COMPATIBILITY:
784       return 130;
785    case PIPE_CAP_ESSL_FEATURE_LEVEL:
786       return 120;
787 
788    case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
789       return 16;
790 
791    case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE:
792       return 65536;
793 
794    case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
795       return 64;
796 
797    case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
798       return 1;
799 
800    case PIPE_CAP_MAX_TEXTURE_2D_SIZE:
801       return 16384;
802    case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
803    case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
804       return 13;
805 
806    case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
807       return 0;
808 
809    case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
810    case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
811    case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
812    case PIPE_CAP_TGSI_TEXCOORD:
813    case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL:
814    case PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL:
815    case PIPE_CAP_SEAMLESS_CUBE_MAP:
816    case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
817       return true;
818    case PIPE_CAP_TGSI_FS_POINT_IS_SYSVAL:
819       return false;
820 
821    case PIPE_CAP_MAX_VERTEX_ELEMENT_SRC_OFFSET:
822       return 0xffff;
823 
824    case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
825       return 0;
826 
827    case PIPE_CAP_ENDIANNESS:
828       return PIPE_ENDIAN_LITTLE;
829 
830    case PIPE_CAP_VIDEO_MEMORY: {
831       uint64_t system_memory;
832 
833       if (!os_get_total_physical_memory(&system_memory))
834          return 0;
835 
836       return (int)(system_memory >> 20);
837    }
838 
839    case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT:
840       return 4;
841 
842    case PIPE_CAP_MAX_VARYINGS:
843       return 16;
844 
845    case PIPE_CAP_FLATSHADE:
846    case PIPE_CAP_TWO_SIDED_COLOR:
847    case PIPE_CAP_ALPHA_TEST:
848    case PIPE_CAP_CLIP_PLANES:
849    case PIPE_CAP_NIR_IMAGES_AS_DEREF:
850       return 0;
851 
852    case PIPE_CAP_SHAREABLE_SHADERS:
853       return 1;
854 
855    default:
856       return u_pipe_screen_get_param_defaults(pscreen, param);
857    }
858 }
859 
860 static float
agx_get_paramf(struct pipe_screen * pscreen,enum pipe_capf param)861 agx_get_paramf(struct pipe_screen* pscreen,
862                enum pipe_capf param)
863 {
864    switch (param) {
865    case PIPE_CAPF_MAX_LINE_WIDTH:
866    case PIPE_CAPF_MAX_LINE_WIDTH_AA:
867       return 16.0; /* Off-by-one fixed point 4:4 encoding */
868 
869    case PIPE_CAPF_MAX_POINT_WIDTH:
870    case PIPE_CAPF_MAX_POINT_WIDTH_AA:
871       return 511.95f;
872 
873    case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY:
874       return 16.0;
875 
876    case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:
877       return 16.0; /* arbitrary */
878 
879    case PIPE_CAPF_MIN_CONSERVATIVE_RASTER_DILATE:
880    case PIPE_CAPF_MAX_CONSERVATIVE_RASTER_DILATE:
881    case PIPE_CAPF_CONSERVATIVE_RASTER_DILATE_GRANULARITY:
882       return 0.0f;
883 
884    default:
885       debug_printf("Unexpected PIPE_CAPF %d query\n", param);
886       return 0.0;
887    }
888 }
889 
890 static int
agx_get_shader_param(struct pipe_screen * pscreen,enum pipe_shader_type shader,enum pipe_shader_cap param)891 agx_get_shader_param(struct pipe_screen* pscreen,
892                      enum pipe_shader_type shader,
893                      enum pipe_shader_cap param)
894 {
895    bool is_deqp = agx_device(pscreen)->debug & AGX_DBG_DEQP;
896    bool is_no16 = agx_device(pscreen)->debug & AGX_DBG_NO16;
897 
898    if (shader != PIPE_SHADER_VERTEX &&
899        shader != PIPE_SHADER_FRAGMENT)
900       return 0;
901 
902    /* this is probably not totally correct.. but it's a start: */
903    switch (param) {
904    case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
905    case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
906    case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
907    case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
908       return 16384;
909 
910    case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
911       return 1024;
912 
913    case PIPE_SHADER_CAP_MAX_INPUTS:
914       return 16;
915 
916    case PIPE_SHADER_CAP_MAX_OUTPUTS:
917       return shader == PIPE_SHADER_FRAGMENT ? 4 : 16;
918 
919    case PIPE_SHADER_CAP_MAX_TEMPS:
920       return 256; /* GL_MAX_PROGRAM_TEMPORARIES_ARB */
921 
922    case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE:
923       return 16 * 1024 * sizeof(float);
924 
925    case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
926       return 16;
927 
928    case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
929       return 0;
930 
931    case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
932    case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
933    case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
934    case PIPE_SHADER_CAP_SUBROUTINES:
935    case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED:
936       return 0;
937 
938    case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
939       return is_deqp;
940 
941    case PIPE_SHADER_CAP_INTEGERS:
942       return true;
943 
944    case PIPE_SHADER_CAP_FP16:
945    case PIPE_SHADER_CAP_GLSL_16BIT_CONSTS:
946    case PIPE_SHADER_CAP_FP16_DERIVATIVES:
947    case PIPE_SHADER_CAP_FP16_CONST_BUFFERS:
948    case PIPE_SHADER_CAP_INT16:
949       return !is_no16;
950 
951    case PIPE_SHADER_CAP_INT64_ATOMICS:
952    case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED:
953    case PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED:
954    case PIPE_SHADER_CAP_TGSI_LDEXP_SUPPORTED:
955    case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED:
956    case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE:
957       return 0;
958 
959    case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
960    case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS:
961       return 16; /* XXX: How many? */
962 
963    case PIPE_SHADER_CAP_PREFERRED_IR:
964       return PIPE_SHADER_IR_NIR;
965 
966    case PIPE_SHADER_CAP_SUPPORTED_IRS:
967       return (1 << PIPE_SHADER_IR_NIR) | (1 << PIPE_SHADER_IR_NIR_SERIALIZED);
968 
969    case PIPE_SHADER_CAP_MAX_UNROLL_ITERATIONS_HINT:
970       return 32;
971 
972    case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS:
973    case PIPE_SHADER_CAP_MAX_SHADER_IMAGES:
974    case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTERS:
975    case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTER_BUFFERS:
976    case PIPE_SHADER_CAP_TGSI_SKIP_MERGE_REGISTERS:
977    case PIPE_SHADER_CAP_LOWER_IF_THRESHOLD:
978       return 0;
979 
980    default:
981       /* Other params are unknown */
982       return 0;
983    }
984 
985    return 0;
986 }
987 
988 static int
agx_get_compute_param(struct pipe_screen * pscreen,enum pipe_shader_ir ir_type,enum pipe_compute_cap param,void * ret)989 agx_get_compute_param(struct pipe_screen *pscreen,
990                       enum pipe_shader_ir ir_type,
991                       enum pipe_compute_cap param,
992                       void *ret)
993 {
994    return 0;
995 }
996 
997 static bool
agx_is_format_supported(struct pipe_screen * pscreen,enum pipe_format format,enum pipe_texture_target target,unsigned sample_count,unsigned storage_sample_count,unsigned usage)998 agx_is_format_supported(struct pipe_screen* pscreen,
999                         enum pipe_format format,
1000                         enum pipe_texture_target target,
1001                         unsigned sample_count,
1002                         unsigned storage_sample_count,
1003                         unsigned usage)
1004 {
1005    const struct util_format_description *format_desc;
1006 
1007    assert(target == PIPE_BUFFER ||
1008           target == PIPE_TEXTURE_1D ||
1009           target == PIPE_TEXTURE_1D_ARRAY ||
1010           target == PIPE_TEXTURE_2D ||
1011           target == PIPE_TEXTURE_2D_ARRAY ||
1012           target == PIPE_TEXTURE_RECT ||
1013           target == PIPE_TEXTURE_3D ||
1014           target == PIPE_TEXTURE_CUBE ||
1015           target == PIPE_TEXTURE_CUBE_ARRAY);
1016 
1017    format_desc = util_format_description(format);
1018 
1019    if (!format_desc)
1020       return false;
1021 
1022    if (sample_count > 1)
1023       return false;
1024 
1025    if (MAX2(sample_count, 1) != MAX2(storage_sample_count, 1))
1026       return false;
1027 
1028    if (usage & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW)) {
1029       struct agx_pixel_format_entry ent = agx_pixel_format[format];
1030 
1031       if (!agx_is_valid_pixel_format(format))
1032          return false;
1033 
1034       if ((usage & PIPE_BIND_RENDER_TARGET) && !ent.renderable)
1035          return false;
1036    }
1037 
1038    /* TODO: formats */
1039    if (usage & PIPE_BIND_VERTEX_BUFFER) {
1040       switch (format) {
1041       case PIPE_FORMAT_R16_FLOAT:
1042       case PIPE_FORMAT_R16G16_FLOAT:
1043       case PIPE_FORMAT_R16G16B16_FLOAT:
1044       case PIPE_FORMAT_R16G16B16A16_FLOAT:
1045       case PIPE_FORMAT_R32_FLOAT:
1046       case PIPE_FORMAT_R32G32_FLOAT:
1047       case PIPE_FORMAT_R32G32B32_FLOAT:
1048       case PIPE_FORMAT_R32G32B32A32_FLOAT:
1049          return true;
1050       default:
1051          return false;
1052       }
1053    }
1054 
1055    /* TODO */
1056    return true;
1057 }
1058 
1059 static uint64_t
agx_get_timestamp(struct pipe_screen * pscreen)1060 agx_get_timestamp(struct pipe_screen *pscreen)
1061 {
1062    return 0;
1063 }
1064 
1065 static void
agx_destroy_screen(struct pipe_screen * screen)1066 agx_destroy_screen(struct pipe_screen *screen)
1067 {
1068    agx_close_device(agx_device(screen));
1069    ralloc_free(screen);
1070 }
1071 
1072 static void
agx_fence_reference(struct pipe_screen * screen,struct pipe_fence_handle ** ptr,struct pipe_fence_handle * fence)1073 agx_fence_reference(struct pipe_screen *screen,
1074                     struct pipe_fence_handle **ptr,
1075                     struct pipe_fence_handle *fence)
1076 {
1077 }
1078 
1079 static bool
agx_fence_finish(struct pipe_screen * screen,struct pipe_context * ctx,struct pipe_fence_handle * fence,uint64_t timeout)1080 agx_fence_finish(struct pipe_screen *screen,
1081                  struct pipe_context *ctx,
1082                  struct pipe_fence_handle *fence,
1083                  uint64_t timeout)
1084 {
1085    return true;
1086 }
1087 
1088 static const void *
agx_get_compiler_options(struct pipe_screen * pscreen,enum pipe_shader_ir ir,enum pipe_shader_type shader)1089 agx_get_compiler_options(struct pipe_screen *pscreen,
1090                          enum pipe_shader_ir ir,
1091                          enum pipe_shader_type shader)
1092 {
1093    return &agx_nir_options;
1094 }
1095 
1096 struct pipe_screen *
agx_screen_create(struct sw_winsys * winsys)1097 agx_screen_create(struct sw_winsys *winsys)
1098 {
1099    struct agx_screen *agx_screen;
1100    struct pipe_screen *screen;
1101 
1102    agx_screen = rzalloc(NULL, struct agx_screen);
1103    if (!agx_screen)
1104       return NULL;
1105 
1106    screen = &agx_screen->pscreen;
1107    agx_screen->winsys = winsys;
1108 
1109    /* Set debug before opening */
1110    agx_screen->dev.debug =
1111       debug_get_flags_option("ASAHI_MESA_DEBUG", agx_debug_options, 0);
1112 
1113    /* Try to open an AGX device */
1114    if (!agx_open_device(screen, &agx_screen->dev)) {
1115       ralloc_free(agx_screen);
1116       return NULL;
1117    }
1118 
1119    screen->destroy = agx_destroy_screen;
1120    screen->get_name = agx_get_name;
1121    screen->get_vendor = agx_get_vendor;
1122    screen->get_device_vendor = agx_get_device_vendor;
1123    screen->get_param = agx_get_param;
1124    screen->get_shader_param = agx_get_shader_param;
1125    screen->get_compute_param = agx_get_compute_param;
1126    screen->get_paramf = agx_get_paramf;
1127    screen->is_format_supported = agx_is_format_supported;
1128    screen->context_create = agx_create_context;
1129    screen->resource_create = agx_resource_create;
1130    screen->resource_from_handle = agx_resource_from_handle;
1131    screen->resource_get_handle = agx_resource_get_handle;
1132    screen->resource_destroy = agx_resource_destroy;
1133    screen->flush_frontbuffer = agx_flush_frontbuffer;
1134    screen->get_timestamp = agx_get_timestamp;
1135    screen->fence_reference = agx_fence_reference;
1136    screen->fence_finish = agx_fence_finish;
1137    screen->get_compiler_options = agx_get_compiler_options;
1138 
1139    agx_internal_shaders(&agx_screen->dev);
1140 
1141    return screen;
1142 }
1143