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 51static 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 58void agx_init_state_functions(struct pipe_context *ctx); 59 60static struct pipe_query * 61agx_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 68static void 69agx_destroy_query(struct pipe_context *ctx, struct pipe_query *query) 70{ 71 FREE(query); 72} 73 74static bool 75agx_begin_query(struct pipe_context *ctx, struct pipe_query *query) 76{ 77 return true; 78} 79 80static bool 81agx_end_query(struct pipe_context *ctx, struct pipe_query *query) 82{ 83 return true; 84} 85 86static bool 87agx_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 98static void 99agx_set_active_query_state(struct pipe_context *pipe, bool enable) 100{ 101} 102 103 104/* 105 * resource 106 */ 107 108static struct pipe_resource * 109agx_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 117static bool 118agx_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 127static inline bool 128agx_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 140static bool 141agx_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 155static bool 156agx_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 180static struct pipe_resource * 181agx_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 263static uint8_t * 264agx_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 273static void 274agx_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 295static void 296agx_transfer_flush_region(struct pipe_context *pipe, 297 struct pipe_transfer *transfer, 298 const struct pipe_box *box) 299{ 300} 301 302static void * 303agx_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 366static void 367agx_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 */ 408static void 409agx_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 418static void 419agx_flush_resource(struct pipe_context *ctx, 420 struct pipe_resource *resource) 421{ 422} 423 424/* 425 * context 426 */ 427static void 428agx_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 589static void 590agx_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 605static void 606agx_invalidate_resource(struct pipe_context *ctx, 607 struct pipe_resource *resource) 608{ 609} 610 611static struct pipe_context * 612agx_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 670static void 671agx_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 697static const char * 698agx_get_vendor(struct pipe_screen* pscreen) 699{ 700 return "Asahi"; 701} 702 703static const char * 704agx_get_device_vendor(struct pipe_screen* pscreen) 705{ 706 return "Apple"; 707} 708 709static const char * 710agx_get_name(struct pipe_screen* pscreen) 711{ 712 return "Apple M1 (G13G B0)"; 713} 714 715static int 716agx_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 860static float 861agx_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 890static int 891agx_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 988static int 989agx_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 997static bool 998agx_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 1059static uint64_t 1060agx_get_timestamp(struct pipe_screen *pscreen) 1061{ 1062 return 0; 1063} 1064 1065static void 1066agx_destroy_screen(struct pipe_screen *screen) 1067{ 1068 agx_close_device(agx_device(screen)); 1069 ralloc_free(screen); 1070} 1071 1072static void 1073agx_fence_reference(struct pipe_screen *screen, 1074 struct pipe_fence_handle **ptr, 1075 struct pipe_fence_handle *fence) 1076{ 1077} 1078 1079static bool 1080agx_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 1088static const void * 1089agx_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 1096struct pipe_screen * 1097agx_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