17ec681f3Smrg/* 27ec681f3Smrg * Copyright 2010 Red Hat Inc. 37ec681f3Smrg * Copyright © 2014-2017 Broadcom 47ec681f3Smrg * Copyright (C) 2019-2020 Collabora, Ltd. 57ec681f3Smrg * Copyright 2006 VMware, Inc. 67ec681f3Smrg * 77ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 87ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 97ec681f3Smrg * to deal in the Software without restriction, including without limitation 107ec681f3Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub 117ec681f3Smrg * license, and/or sell copies of the Software, and to permit persons to whom 127ec681f3Smrg * the Software is furnished to do so, subject to the following conditions: 137ec681f3Smrg * 147ec681f3Smrg * The above copyright notice and this permission notice (including the next 157ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 167ec681f3Smrg * Software. 177ec681f3Smrg * 187ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 197ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 207ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 217ec681f3Smrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 227ec681f3Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 237ec681f3Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 247ec681f3Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE. 257ec681f3Smrg */ 267ec681f3Smrg#include <stdio.h> 277ec681f3Smrg#include <errno.h> 287ec681f3Smrg#include "pipe/p_defines.h" 297ec681f3Smrg#include "pipe/p_state.h" 307ec681f3Smrg#include "pipe/p_context.h" 317ec681f3Smrg#include "pipe/p_screen.h" 327ec681f3Smrg#include "util/u_memory.h" 337ec681f3Smrg#include "util/u_screen.h" 347ec681f3Smrg#include "util/u_inlines.h" 357ec681f3Smrg#include "util/format/u_format.h" 367ec681f3Smrg#include "util/u_upload_mgr.h" 377ec681f3Smrg#include "util/half_float.h" 387ec681f3Smrg#include "frontend/winsys_handle.h" 397ec681f3Smrg#include "frontend/sw_winsys.h" 407ec681f3Smrg#include "gallium/auxiliary/util/u_transfer.h" 417ec681f3Smrg#include "gallium/auxiliary/util/u_surface.h" 427ec681f3Smrg#include "gallium/auxiliary/util/u_framebuffer.h" 437ec681f3Smrg#include "agx_public.h" 447ec681f3Smrg#include "agx_state.h" 457ec681f3Smrg#include "magic.h" 467ec681f3Smrg#include "asahi/compiler/agx_compile.h" 477ec681f3Smrg#include "asahi/lib/decode.h" 487ec681f3Smrg#include "asahi/lib/tiling.h" 497ec681f3Smrg#include "asahi/lib/agx_formats.h" 507ec681f3Smrg 517ec681f3Smrgstatic const struct debug_named_value agx_debug_options[] = { 527ec681f3Smrg {"trace", AGX_DBG_TRACE, "Trace the command stream"}, 537ec681f3Smrg {"deqp", AGX_DBG_DEQP, "Hacks for dEQP"}, 547ec681f3Smrg {"no16", AGX_DBG_NO16, "Disable 16-bit support"}, 557ec681f3Smrg DEBUG_NAMED_VALUE_END 567ec681f3Smrg}; 577ec681f3Smrg 587ec681f3Smrgvoid agx_init_state_functions(struct pipe_context *ctx); 597ec681f3Smrg 607ec681f3Smrgstatic struct pipe_query * 617ec681f3Smrgagx_create_query(struct pipe_context *ctx, unsigned query_type, unsigned index) 627ec681f3Smrg{ 637ec681f3Smrg struct agx_query *query = CALLOC_STRUCT(agx_query); 647ec681f3Smrg 657ec681f3Smrg return (struct pipe_query *)query; 667ec681f3Smrg} 677ec681f3Smrg 687ec681f3Smrgstatic void 697ec681f3Smrgagx_destroy_query(struct pipe_context *ctx, struct pipe_query *query) 707ec681f3Smrg{ 717ec681f3Smrg FREE(query); 727ec681f3Smrg} 737ec681f3Smrg 747ec681f3Smrgstatic bool 757ec681f3Smrgagx_begin_query(struct pipe_context *ctx, struct pipe_query *query) 767ec681f3Smrg{ 777ec681f3Smrg return true; 787ec681f3Smrg} 797ec681f3Smrg 807ec681f3Smrgstatic bool 817ec681f3Smrgagx_end_query(struct pipe_context *ctx, struct pipe_query *query) 827ec681f3Smrg{ 837ec681f3Smrg return true; 847ec681f3Smrg} 857ec681f3Smrg 867ec681f3Smrgstatic bool 877ec681f3Smrgagx_get_query_result(struct pipe_context *ctx, 887ec681f3Smrg struct pipe_query *query, 897ec681f3Smrg bool wait, 907ec681f3Smrg union pipe_query_result *vresult) 917ec681f3Smrg{ 927ec681f3Smrg uint64_t *result = (uint64_t*)vresult; 937ec681f3Smrg 947ec681f3Smrg *result = 0; 957ec681f3Smrg return true; 967ec681f3Smrg} 977ec681f3Smrg 987ec681f3Smrgstatic void 997ec681f3Smrgagx_set_active_query_state(struct pipe_context *pipe, bool enable) 1007ec681f3Smrg{ 1017ec681f3Smrg} 1027ec681f3Smrg 1037ec681f3Smrg 1047ec681f3Smrg/* 1057ec681f3Smrg * resource 1067ec681f3Smrg */ 1077ec681f3Smrg 1087ec681f3Smrgstatic struct pipe_resource * 1097ec681f3Smrgagx_resource_from_handle(struct pipe_screen *pscreen, 1107ec681f3Smrg const struct pipe_resource *templat, 1117ec681f3Smrg struct winsys_handle *whandle, 1127ec681f3Smrg unsigned usage) 1137ec681f3Smrg{ 1147ec681f3Smrg unreachable("Imports todo"); 1157ec681f3Smrg} 1167ec681f3Smrg 1177ec681f3Smrgstatic bool 1187ec681f3Smrgagx_resource_get_handle(struct pipe_screen *pscreen, 1197ec681f3Smrg struct pipe_context *ctx, 1207ec681f3Smrg struct pipe_resource *pt, 1217ec681f3Smrg struct winsys_handle *handle, 1227ec681f3Smrg unsigned usage) 1237ec681f3Smrg{ 1247ec681f3Smrg unreachable("Handles todo"); 1257ec681f3Smrg} 1267ec681f3Smrg 1277ec681f3Smrgstatic inline bool 1287ec681f3Smrgagx_is_2d(const struct agx_resource *pres) 1297ec681f3Smrg{ 1307ec681f3Smrg switch (pres->base.target) { 1317ec681f3Smrg case PIPE_TEXTURE_2D: 1327ec681f3Smrg case PIPE_TEXTURE_RECT: 1337ec681f3Smrg case PIPE_TEXTURE_CUBE: 1347ec681f3Smrg return true; 1357ec681f3Smrg default: 1367ec681f3Smrg return false; 1377ec681f3Smrg } 1387ec681f3Smrg} 1397ec681f3Smrg 1407ec681f3Smrgstatic bool 1417ec681f3Smrgagx_must_tile(const struct agx_resource *pres) 1427ec681f3Smrg{ 1437ec681f3Smrg switch (pres->base.target) { 1447ec681f3Smrg case PIPE_TEXTURE_CUBE: 1457ec681f3Smrg case PIPE_TEXTURE_3D: 1467ec681f3Smrg /* We don't know how to do linear for these */ 1477ec681f3Smrg return true; 1487ec681f3Smrg default: 1497ec681f3Smrg break; 1507ec681f3Smrg } 1517ec681f3Smrg 1527ec681f3Smrg return false; 1537ec681f3Smrg} 1547ec681f3Smrg 1557ec681f3Smrgstatic bool 1567ec681f3Smrgagx_should_tile(const struct agx_resource *pres) 1577ec681f3Smrg{ 1587ec681f3Smrg const unsigned valid_binding = 1597ec681f3Smrg PIPE_BIND_DEPTH_STENCIL | 1607ec681f3Smrg PIPE_BIND_RENDER_TARGET | 1617ec681f3Smrg PIPE_BIND_BLENDABLE | 1627ec681f3Smrg PIPE_BIND_SAMPLER_VIEW | 1637ec681f3Smrg PIPE_BIND_DISPLAY_TARGET | 1647ec681f3Smrg PIPE_BIND_SCANOUT | 1657ec681f3Smrg PIPE_BIND_SHARED; 1667ec681f3Smrg 1677ec681f3Smrg unsigned bpp = util_format_get_blocksizebits(pres->base.format); 1687ec681f3Smrg 1697ec681f3Smrg bool can_tile = agx_is_2d(pres) 1707ec681f3Smrg && (bpp == 32) 1717ec681f3Smrg && ((pres->base.bind & ~valid_binding) == 0); 1727ec681f3Smrg 1737ec681f3Smrg bool should_tile = (pres->base.usage != PIPE_USAGE_STREAM); 1747ec681f3Smrg bool must_tile = agx_must_tile(pres); 1757ec681f3Smrg 1767ec681f3Smrg assert(!(must_tile && !can_tile)); 1777ec681f3Smrg return must_tile || (can_tile && should_tile); 1787ec681f3Smrg} 1797ec681f3Smrg 1807ec681f3Smrgstatic struct pipe_resource * 1817ec681f3Smrgagx_resource_create(struct pipe_screen *screen, 1827ec681f3Smrg const struct pipe_resource *templ) 1837ec681f3Smrg{ 1847ec681f3Smrg struct agx_device *dev = agx_device(screen); 1857ec681f3Smrg struct agx_resource *nresource; 1867ec681f3Smrg 1877ec681f3Smrg nresource = CALLOC_STRUCT(agx_resource); 1887ec681f3Smrg if (!nresource) 1897ec681f3Smrg return NULL; 1907ec681f3Smrg 1917ec681f3Smrg nresource->base = *templ; 1927ec681f3Smrg nresource->base.screen = screen; 1937ec681f3Smrg 1947ec681f3Smrg nresource->modifier = agx_should_tile(nresource) ? 1957ec681f3Smrg DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER : DRM_FORMAT_MOD_LINEAR; 1967ec681f3Smrg 1977ec681f3Smrg unsigned offset = 0; 1987ec681f3Smrg 1997ec681f3Smrg for (unsigned l = 0; l <= templ->last_level; ++l) { 2007ec681f3Smrg unsigned width = u_minify(templ->width0, l); 2017ec681f3Smrg unsigned height = u_minify(templ->height0, l); 2027ec681f3Smrg 2037ec681f3Smrg if (nresource->modifier == DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER) { 2047ec681f3Smrg width = ALIGN_POT(width, 64); 2057ec681f3Smrg height = ALIGN_POT(height, 64); 2067ec681f3Smrg } 2077ec681f3Smrg 2087ec681f3Smrg nresource->slices[l].line_stride = 2097ec681f3Smrg util_format_get_stride(templ->format, width); 2107ec681f3Smrg 2117ec681f3Smrg nresource->slices[l].offset = offset; 2127ec681f3Smrg offset += ALIGN_POT(nresource->slices[l].line_stride * height, 0x80); 2137ec681f3Smrg } 2147ec681f3Smrg 2157ec681f3Smrg /* Arrays and cubemaps have the entire miptree duplicated */ 2167ec681f3Smrg nresource->array_stride = ALIGN_POT(offset, 64); 2177ec681f3Smrg unsigned size = ALIGN_POT(nresource->array_stride * templ->array_size, 4096); 2187ec681f3Smrg 2197ec681f3Smrg pipe_reference_init(&nresource->base.reference, 1); 2207ec681f3Smrg 2217ec681f3Smrg struct sw_winsys *winsys = ((struct agx_screen *) screen)->winsys; 2227ec681f3Smrg 2237ec681f3Smrg if (templ->bind & (PIPE_BIND_DISPLAY_TARGET | 2247ec681f3Smrg PIPE_BIND_SCANOUT | 2257ec681f3Smrg PIPE_BIND_SHARED)) { 2267ec681f3Smrg unsigned width0 = templ->width0, height0 = templ->height0; 2277ec681f3Smrg 2287ec681f3Smrg if (nresource->modifier == DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER) { 2297ec681f3Smrg width0 = ALIGN_POT(width0, 64); 2307ec681f3Smrg height0 = ALIGN_POT(height0, 64); 2317ec681f3Smrg } 2327ec681f3Smrg 2337ec681f3Smrg nresource->dt = winsys->displaytarget_create(winsys, 2347ec681f3Smrg templ->bind, 2357ec681f3Smrg templ->format, 2367ec681f3Smrg width0, 2377ec681f3Smrg height0, 2387ec681f3Smrg 64, 2397ec681f3Smrg NULL /*map_front_private*/, 2407ec681f3Smrg &nresource->dt_stride); 2417ec681f3Smrg 2427ec681f3Smrg nresource->slices[0].line_stride = nresource->dt_stride; 2437ec681f3Smrg assert((nresource->dt_stride & 0xF) == 0); 2447ec681f3Smrg 2457ec681f3Smrg offset = nresource->slices[0].line_stride * ALIGN_POT(templ->height0, 64); 2467ec681f3Smrg 2477ec681f3Smrg if (nresource->dt == NULL) { 2487ec681f3Smrg FREE(nresource); 2497ec681f3Smrg return NULL; 2507ec681f3Smrg } 2517ec681f3Smrg } 2527ec681f3Smrg 2537ec681f3Smrg nresource->bo = agx_bo_create(dev, size, AGX_MEMORY_TYPE_FRAMEBUFFER); 2547ec681f3Smrg 2557ec681f3Smrg if (!nresource->bo) { 2567ec681f3Smrg FREE(nresource); 2577ec681f3Smrg return NULL; 2587ec681f3Smrg } 2597ec681f3Smrg 2607ec681f3Smrg return &nresource->base; 2617ec681f3Smrg} 2627ec681f3Smrg 2637ec681f3Smrgstatic uint8_t * 2647ec681f3Smrgagx_rsrc_offset(struct agx_resource *rsrc, unsigned level, unsigned z) 2657ec681f3Smrg{ 2667ec681f3Smrg struct agx_bo *bo = rsrc->bo; 2677ec681f3Smrg uint8_t *map = ((uint8_t *) bo->ptr.cpu) + rsrc->slices[level].offset; 2687ec681f3Smrg map += z * rsrc->array_stride; 2697ec681f3Smrg 2707ec681f3Smrg return map; 2717ec681f3Smrg} 2727ec681f3Smrg 2737ec681f3Smrgstatic void 2747ec681f3Smrgagx_resource_destroy(struct pipe_screen *screen, 2757ec681f3Smrg struct pipe_resource *prsrc) 2767ec681f3Smrg{ 2777ec681f3Smrg struct agx_resource *rsrc = (struct agx_resource *)prsrc; 2787ec681f3Smrg 2797ec681f3Smrg if (rsrc->dt) { 2807ec681f3Smrg /* display target */ 2817ec681f3Smrg struct agx_screen *agx_screen = (struct agx_screen*)screen; 2827ec681f3Smrg struct sw_winsys *winsys = agx_screen->winsys; 2837ec681f3Smrg winsys->displaytarget_destroy(winsys, rsrc->dt); 2847ec681f3Smrg } 2857ec681f3Smrg 2867ec681f3Smrg agx_bo_unreference(rsrc->bo); 2877ec681f3Smrg FREE(rsrc); 2887ec681f3Smrg} 2897ec681f3Smrg 2907ec681f3Smrg 2917ec681f3Smrg/* 2927ec681f3Smrg * transfer 2937ec681f3Smrg */ 2947ec681f3Smrg 2957ec681f3Smrgstatic void 2967ec681f3Smrgagx_transfer_flush_region(struct pipe_context *pipe, 2977ec681f3Smrg struct pipe_transfer *transfer, 2987ec681f3Smrg const struct pipe_box *box) 2997ec681f3Smrg{ 3007ec681f3Smrg} 3017ec681f3Smrg 3027ec681f3Smrgstatic void * 3037ec681f3Smrgagx_transfer_map(struct pipe_context *pctx, 3047ec681f3Smrg struct pipe_resource *resource, 3057ec681f3Smrg unsigned level, 3067ec681f3Smrg unsigned usage, /* a combination of PIPE_MAP_x */ 3077ec681f3Smrg const struct pipe_box *box, 3087ec681f3Smrg struct pipe_transfer **out_transfer) 3097ec681f3Smrg{ 3107ec681f3Smrg struct agx_context *ctx = agx_context(pctx); 3117ec681f3Smrg struct agx_resource *rsrc = agx_resource(resource); 3127ec681f3Smrg unsigned bytes_per_pixel = util_format_get_blocksize(resource->format); 3137ec681f3Smrg 3147ec681f3Smrg /* Can't map tiled/compressed directly */ 3157ec681f3Smrg if ((usage & PIPE_MAP_DIRECTLY) && rsrc->modifier != DRM_FORMAT_MOD_LINEAR) 3167ec681f3Smrg return NULL; 3177ec681f3Smrg 3187ec681f3Smrg if (ctx->batch->cbufs[0] && resource == ctx->batch->cbufs[0]->texture) 3197ec681f3Smrg pctx->flush(pctx, NULL, 0); 3207ec681f3Smrg if (ctx->batch->zsbuf && resource == ctx->batch->zsbuf->texture) 3217ec681f3Smrg pctx->flush(pctx, NULL, 0); 3227ec681f3Smrg 3237ec681f3Smrg struct agx_transfer *transfer = CALLOC_STRUCT(agx_transfer); 3247ec681f3Smrg transfer->base.level = level; 3257ec681f3Smrg transfer->base.usage = usage; 3267ec681f3Smrg transfer->base.box = *box; 3277ec681f3Smrg 3287ec681f3Smrg pipe_resource_reference(&transfer->base.resource, resource); 3297ec681f3Smrg *out_transfer = &transfer->base; 3307ec681f3Smrg 3317ec681f3Smrg if (rsrc->modifier == DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER) { 3327ec681f3Smrg transfer->base.stride = box->width * bytes_per_pixel; 3337ec681f3Smrg transfer->base.layer_stride = transfer->base.stride * box->height; 3347ec681f3Smrg transfer->map = calloc(transfer->base.layer_stride, box->depth); 3357ec681f3Smrg assert(box->depth == 1); 3367ec681f3Smrg 3377ec681f3Smrg if ((usage & PIPE_MAP_READ) && BITSET_TEST(rsrc->data_valid, level)) { 3387ec681f3Smrg for (unsigned z = 0; z < box->depth; ++z) { 3397ec681f3Smrg uint8_t *map = agx_rsrc_offset(rsrc, level, box->z + z); 3407ec681f3Smrg 3417ec681f3Smrg agx_detile(map, transfer->map, 3427ec681f3Smrg u_minify(resource->width0, level), bytes_per_pixel * 8, 3437ec681f3Smrg transfer->base.stride / bytes_per_pixel, 3447ec681f3Smrg box->x, box->y, box->x + box->width, box->y + box->height); 3457ec681f3Smrg } 3467ec681f3Smrg } 3477ec681f3Smrg 3487ec681f3Smrg return transfer->map; 3497ec681f3Smrg } else { 3507ec681f3Smrg assert (rsrc->modifier == DRM_FORMAT_MOD_LINEAR); 3517ec681f3Smrg 3527ec681f3Smrg transfer->base.stride = rsrc->slices[level].line_stride; 3537ec681f3Smrg transfer->base.layer_stride = rsrc->array_stride; 3547ec681f3Smrg 3557ec681f3Smrg /* Be conservative for direct writes */ 3567ec681f3Smrg 3577ec681f3Smrg if ((usage & PIPE_MAP_WRITE) && (usage & PIPE_MAP_DIRECTLY)) 3587ec681f3Smrg BITSET_SET(rsrc->data_valid, level); 3597ec681f3Smrg 3607ec681f3Smrg return agx_rsrc_offset(rsrc, level, box->z) 3617ec681f3Smrg + transfer->base.box.y * rsrc->slices[level].line_stride 3627ec681f3Smrg + transfer->base.box.x * bytes_per_pixel; 3637ec681f3Smrg } 3647ec681f3Smrg} 3657ec681f3Smrg 3667ec681f3Smrgstatic void 3677ec681f3Smrgagx_transfer_unmap(struct pipe_context *pctx, 3687ec681f3Smrg struct pipe_transfer *transfer) 3697ec681f3Smrg{ 3707ec681f3Smrg /* Gallium expects writeback here, so we tile */ 3717ec681f3Smrg 3727ec681f3Smrg struct agx_transfer *trans = agx_transfer(transfer); 3737ec681f3Smrg struct pipe_resource *prsrc = transfer->resource; 3747ec681f3Smrg struct agx_resource *rsrc = (struct agx_resource *) prsrc; 3757ec681f3Smrg unsigned bytes_per_pixel = util_format_get_blocksize(prsrc->format); 3767ec681f3Smrg 3777ec681f3Smrg if (transfer->usage & PIPE_MAP_WRITE) 3787ec681f3Smrg BITSET_SET(rsrc->data_valid, transfer->level); 3797ec681f3Smrg 3807ec681f3Smrg /* Tiling will occur in software from a staging cpu buffer */ 3817ec681f3Smrg if ((transfer->usage & PIPE_MAP_WRITE) && 3827ec681f3Smrg rsrc->modifier == DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER) { 3837ec681f3Smrg assert(trans->map != NULL); 3847ec681f3Smrg 3857ec681f3Smrg for (unsigned z = 0; z < transfer->box.depth; ++z) { 3867ec681f3Smrg uint8_t *map = agx_rsrc_offset(rsrc, transfer->level, 3877ec681f3Smrg transfer->box.z + z); 3887ec681f3Smrg 3897ec681f3Smrg agx_tile(map, trans->map, 3907ec681f3Smrg u_minify(transfer->resource->width0, transfer->level), 3917ec681f3Smrg bytes_per_pixel * 8, 3927ec681f3Smrg transfer->stride / bytes_per_pixel, 3937ec681f3Smrg transfer->box.x, transfer->box.y, 3947ec681f3Smrg transfer->box.x + transfer->box.width, 3957ec681f3Smrg transfer->box.y + transfer->box.height); 3967ec681f3Smrg } 3977ec681f3Smrg } 3987ec681f3Smrg 3997ec681f3Smrg /* Free the transfer */ 4007ec681f3Smrg free(trans->map); 4017ec681f3Smrg pipe_resource_reference(&transfer->resource, NULL); 4027ec681f3Smrg FREE(transfer); 4037ec681f3Smrg} 4047ec681f3Smrg 4057ec681f3Smrg/* 4067ec681f3Smrg * clear/copy 4077ec681f3Smrg */ 4087ec681f3Smrgstatic void 4097ec681f3Smrgagx_clear(struct pipe_context *pctx, unsigned buffers, const struct pipe_scissor_state *scissor_state, 4107ec681f3Smrg const union pipe_color_union *color, double depth, unsigned stencil) 4117ec681f3Smrg{ 4127ec681f3Smrg struct agx_context *ctx = agx_context(pctx); 4137ec681f3Smrg ctx->batch->clear |= buffers; 4147ec681f3Smrg memcpy(ctx->batch->clear_color, color->f, sizeof(color->f)); 4157ec681f3Smrg} 4167ec681f3Smrg 4177ec681f3Smrg 4187ec681f3Smrgstatic void 4197ec681f3Smrgagx_flush_resource(struct pipe_context *ctx, 4207ec681f3Smrg struct pipe_resource *resource) 4217ec681f3Smrg{ 4227ec681f3Smrg} 4237ec681f3Smrg 4247ec681f3Smrg/* 4257ec681f3Smrg * context 4267ec681f3Smrg */ 4277ec681f3Smrgstatic void 4287ec681f3Smrgagx_flush(struct pipe_context *pctx, 4297ec681f3Smrg struct pipe_fence_handle **fence, 4307ec681f3Smrg unsigned flags) 4317ec681f3Smrg{ 4327ec681f3Smrg struct agx_context *ctx = agx_context(pctx); 4337ec681f3Smrg 4347ec681f3Smrg if (fence) 4357ec681f3Smrg *fence = NULL; 4367ec681f3Smrg 4377ec681f3Smrg /* TODO */ 4387ec681f3Smrg if (!ctx->batch->cbufs[0]) 4397ec681f3Smrg return; 4407ec681f3Smrg 4417ec681f3Smrg /* Nothing to do */ 4427ec681f3Smrg if (!(ctx->batch->draw | ctx->batch->clear)) 4437ec681f3Smrg return; 4447ec681f3Smrg 4457ec681f3Smrg /* Finalize the encoder */ 4467ec681f3Smrg uint8_t stop[5 + 64] = { 0x00, 0x00, 0x00, 0xc0, 0x00 }; 4477ec681f3Smrg memcpy(ctx->batch->encoder_current, stop, sizeof(stop)); 4487ec681f3Smrg 4497ec681f3Smrg /* Emit the commandbuffer */ 4507ec681f3Smrg uint64_t pipeline_clear = 0; 4517ec681f3Smrg bool clear_pipeline_textures = false; 4527ec681f3Smrg 4537ec681f3Smrg struct agx_device *dev = agx_device(pctx->screen); 4547ec681f3Smrg 4557ec681f3Smrg if (ctx->batch->clear & PIPE_CLEAR_COLOR0) { 4567ec681f3Smrg uint16_t clear_colour[4] = { 4577ec681f3Smrg _mesa_float_to_half(ctx->batch->clear_color[0]), 4587ec681f3Smrg _mesa_float_to_half(ctx->batch->clear_color[1]), 4597ec681f3Smrg _mesa_float_to_half(ctx->batch->clear_color[2]), 4607ec681f3Smrg _mesa_float_to_half(ctx->batch->clear_color[3]) 4617ec681f3Smrg }; 4627ec681f3Smrg 4637ec681f3Smrg 4647ec681f3Smrg pipeline_clear = agx_build_clear_pipeline(ctx, 4657ec681f3Smrg dev->internal.clear, 4667ec681f3Smrg agx_pool_upload(&ctx->batch->pool, clear_colour, sizeof(clear_colour))); 4677ec681f3Smrg } else { 4687ec681f3Smrg enum pipe_format fmt = ctx->batch->cbufs[0]->format; 4697ec681f3Smrg enum agx_format internal = agx_pixel_format[fmt].internal; 4707ec681f3Smrg uint32_t shader = dev->reload.format[internal]; 4717ec681f3Smrg 4727ec681f3Smrg pipeline_clear = agx_build_reload_pipeline(ctx, shader, 4737ec681f3Smrg ctx->batch->cbufs[0]); 4747ec681f3Smrg 4757ec681f3Smrg clear_pipeline_textures = true; 4767ec681f3Smrg } 4777ec681f3Smrg 4787ec681f3Smrg uint64_t pipeline_store = 4797ec681f3Smrg agx_build_store_pipeline(ctx, 4807ec681f3Smrg dev->internal.store, 4817ec681f3Smrg agx_pool_upload(&ctx->batch->pool, ctx->render_target[0], sizeof(ctx->render_target))); 4827ec681f3Smrg 4837ec681f3Smrg /* Pipelines must 64 aligned */ 4847ec681f3Smrg struct agx_ptr pipeline_null = 4857ec681f3Smrg agx_pool_alloc_aligned(&ctx->batch->pipeline_pool, 64, 64); 4867ec681f3Smrg memset(pipeline_null.cpu, 0, 64); 4877ec681f3Smrg 4887ec681f3Smrg struct agx_resource *rt0 = agx_resource(ctx->batch->cbufs[0]->texture); 4897ec681f3Smrg BITSET_SET(rt0->data_valid, 0); 4907ec681f3Smrg 4917ec681f3Smrg struct agx_resource *zbuf = ctx->batch->zsbuf ? 4927ec681f3Smrg agx_resource(ctx->batch->zsbuf->texture) : NULL; 4937ec681f3Smrg 4947ec681f3Smrg if (zbuf) 4957ec681f3Smrg BITSET_SET(zbuf->data_valid, 0); 4967ec681f3Smrg 4977ec681f3Smrg /* BO list for a given batch consists of: 4987ec681f3Smrg * - BOs for the batch's framebuffer surfaces 4997ec681f3Smrg * - BOs for the batch's pools 5007ec681f3Smrg * - BOs for the encoder 5017ec681f3Smrg * - BO for internal shaders 5027ec681f3Smrg * - BOs added to the batch explicitly 5037ec681f3Smrg */ 5047ec681f3Smrg struct agx_batch *batch = ctx->batch; 5057ec681f3Smrg 5067ec681f3Smrg agx_batch_add_bo(batch, batch->encoder); 5077ec681f3Smrg agx_batch_add_bo(batch, batch->scissor.bo); 5087ec681f3Smrg agx_batch_add_bo(batch, dev->internal.bo); 5097ec681f3Smrg agx_batch_add_bo(batch, dev->reload.bo); 5107ec681f3Smrg 5117ec681f3Smrg for (unsigned i = 0; i < batch->nr_cbufs; ++i) { 5127ec681f3Smrg struct pipe_surface *surf = batch->cbufs[i]; 5137ec681f3Smrg assert(surf != NULL && surf->texture != NULL); 5147ec681f3Smrg struct agx_resource *rsrc = agx_resource(surf->texture); 5157ec681f3Smrg agx_batch_add_bo(batch, rsrc->bo); 5167ec681f3Smrg } 5177ec681f3Smrg 5187ec681f3Smrg if (batch->zsbuf) { 5197ec681f3Smrg struct pipe_surface *surf = batch->zsbuf; 5207ec681f3Smrg struct agx_resource *rsrc = agx_resource(surf->texture); 5217ec681f3Smrg agx_batch_add_bo(batch, rsrc->bo); 5227ec681f3Smrg } 5237ec681f3Smrg 5247ec681f3Smrg unsigned handle_count = 5257ec681f3Smrg BITSET_COUNT(batch->bo_list) + 5267ec681f3Smrg agx_pool_num_bos(&batch->pool) + 5277ec681f3Smrg agx_pool_num_bos(&batch->pipeline_pool); 5287ec681f3Smrg 5297ec681f3Smrg uint32_t *handles = calloc(sizeof(uint32_t), handle_count); 5307ec681f3Smrg unsigned handle = 0, handle_i = 0; 5317ec681f3Smrg 5327ec681f3Smrg BITSET_FOREACH_SET(handle, batch->bo_list, sizeof(batch->bo_list) * 8) { 5337ec681f3Smrg handles[handle_i++] = handle; 5347ec681f3Smrg } 5357ec681f3Smrg 5367ec681f3Smrg agx_pool_get_bo_handles(&batch->pool, handles + handle_i); 5377ec681f3Smrg handle_i += agx_pool_num_bos(&batch->pool); 5387ec681f3Smrg 5397ec681f3Smrg agx_pool_get_bo_handles(&batch->pipeline_pool, handles + handle_i); 5407ec681f3Smrg handle_i += agx_pool_num_bos(&batch->pipeline_pool); 5417ec681f3Smrg 5427ec681f3Smrg /* Size calculation should've been exact */ 5437ec681f3Smrg assert(handle_i == handle_count); 5447ec681f3Smrg 5457ec681f3Smrg unsigned cmdbuf_id = agx_get_global_id(dev); 5467ec681f3Smrg unsigned encoder_id = agx_get_global_id(dev); 5477ec681f3Smrg 5487ec681f3Smrg unsigned cmdbuf_size = demo_cmdbuf(dev->cmdbuf.ptr.cpu, 5497ec681f3Smrg dev->cmdbuf.size, 5507ec681f3Smrg &ctx->batch->pool, 5517ec681f3Smrg ctx->batch->encoder->ptr.gpu, 5527ec681f3Smrg encoder_id, 5537ec681f3Smrg ctx->batch->scissor.bo->ptr.gpu, 5547ec681f3Smrg ctx->batch->width, 5557ec681f3Smrg ctx->batch->height, 5567ec681f3Smrg pipeline_null.gpu, 5577ec681f3Smrg pipeline_clear, 5587ec681f3Smrg pipeline_store, 5597ec681f3Smrg rt0->bo->ptr.gpu, 5607ec681f3Smrg clear_pipeline_textures); 5617ec681f3Smrg 5627ec681f3Smrg /* Generate the mapping table from the BO list */ 5637ec681f3Smrg demo_mem_map(dev->memmap.ptr.cpu, dev->memmap.size, handles, handle_count, 5647ec681f3Smrg cmdbuf_id, encoder_id, cmdbuf_size); 5657ec681f3Smrg 5667ec681f3Smrg free(handles); 5677ec681f3Smrg 5687ec681f3Smrg agx_submit_cmdbuf(dev, dev->cmdbuf.handle, dev->memmap.handle, dev->queue.id); 5697ec681f3Smrg 5707ec681f3Smrg agx_wait_queue(dev->queue); 5717ec681f3Smrg 5727ec681f3Smrg if (dev->debug & AGX_DBG_TRACE) { 5737ec681f3Smrg agxdecode_cmdstream(dev->cmdbuf.handle, dev->memmap.handle, true); 5747ec681f3Smrg agxdecode_next_frame(); 5757ec681f3Smrg } 5767ec681f3Smrg 5777ec681f3Smrg memset(batch->bo_list, 0, sizeof(batch->bo_list)); 5787ec681f3Smrg agx_pool_cleanup(&ctx->batch->pool); 5797ec681f3Smrg agx_pool_cleanup(&ctx->batch->pipeline_pool); 5807ec681f3Smrg agx_pool_init(&ctx->batch->pool, dev, AGX_MEMORY_TYPE_FRAMEBUFFER, true); 5817ec681f3Smrg agx_pool_init(&ctx->batch->pipeline_pool, dev, AGX_MEMORY_TYPE_CMDBUF_32, true); 5827ec681f3Smrg ctx->batch->clear = 0; 5837ec681f3Smrg ctx->batch->draw = 0; 5847ec681f3Smrg ctx->batch->encoder_current = ctx->batch->encoder->ptr.cpu; 5857ec681f3Smrg ctx->batch->scissor.count = 0; 5867ec681f3Smrg ctx->dirty = ~0; 5877ec681f3Smrg} 5887ec681f3Smrg 5897ec681f3Smrgstatic void 5907ec681f3Smrgagx_destroy_context(struct pipe_context *pctx) 5917ec681f3Smrg{ 5927ec681f3Smrg struct agx_context *ctx = agx_context(pctx); 5937ec681f3Smrg 5947ec681f3Smrg if (pctx->stream_uploader) 5957ec681f3Smrg u_upload_destroy(pctx->stream_uploader); 5967ec681f3Smrg 5977ec681f3Smrg if (ctx->blitter) 5987ec681f3Smrg util_blitter_destroy(ctx->blitter); 5997ec681f3Smrg 6007ec681f3Smrg util_unreference_framebuffer_state(&ctx->framebuffer); 6017ec681f3Smrg 6027ec681f3Smrg FREE(ctx); 6037ec681f3Smrg} 6047ec681f3Smrg 6057ec681f3Smrgstatic void 6067ec681f3Smrgagx_invalidate_resource(struct pipe_context *ctx, 6077ec681f3Smrg struct pipe_resource *resource) 6087ec681f3Smrg{ 6097ec681f3Smrg} 6107ec681f3Smrg 6117ec681f3Smrgstatic struct pipe_context * 6127ec681f3Smrgagx_create_context(struct pipe_screen *screen, 6137ec681f3Smrg void *priv, unsigned flags) 6147ec681f3Smrg{ 6157ec681f3Smrg struct agx_context *ctx = CALLOC_STRUCT(agx_context); 6167ec681f3Smrg struct pipe_context *pctx = &ctx->base; 6177ec681f3Smrg 6187ec681f3Smrg if (!ctx) 6197ec681f3Smrg return NULL; 6207ec681f3Smrg 6217ec681f3Smrg pctx->screen = screen; 6227ec681f3Smrg pctx->priv = priv; 6237ec681f3Smrg 6247ec681f3Smrg ctx->batch = CALLOC_STRUCT(agx_batch); 6257ec681f3Smrg agx_pool_init(&ctx->batch->pool, 6267ec681f3Smrg agx_device(screen), AGX_MEMORY_TYPE_FRAMEBUFFER, true); 6277ec681f3Smrg agx_pool_init(&ctx->batch->pipeline_pool, 6287ec681f3Smrg agx_device(screen), AGX_MEMORY_TYPE_SHADER, true); 6297ec681f3Smrg ctx->batch->encoder = agx_bo_create(agx_device(screen), 0x80000, AGX_MEMORY_TYPE_FRAMEBUFFER); 6307ec681f3Smrg ctx->batch->encoder_current = ctx->batch->encoder->ptr.cpu; 6317ec681f3Smrg ctx->batch->scissor.bo = agx_bo_create(agx_device(screen), 0x80000, AGX_MEMORY_TYPE_FRAMEBUFFER); 6327ec681f3Smrg 6337ec681f3Smrg /* Upload fixed shaders (TODO: compile them?) */ 6347ec681f3Smrg 6357ec681f3Smrg pctx->stream_uploader = u_upload_create_default(pctx); 6367ec681f3Smrg if (!pctx->stream_uploader) { 6377ec681f3Smrg FREE(pctx); 6387ec681f3Smrg return NULL; 6397ec681f3Smrg } 6407ec681f3Smrg pctx->const_uploader = pctx->stream_uploader; 6417ec681f3Smrg 6427ec681f3Smrg pctx->destroy = agx_destroy_context; 6437ec681f3Smrg pctx->flush = agx_flush; 6447ec681f3Smrg pctx->clear = agx_clear; 6457ec681f3Smrg pctx->resource_copy_region = util_resource_copy_region; 6467ec681f3Smrg pctx->blit = agx_blit; 6477ec681f3Smrg pctx->flush_resource = agx_flush_resource; 6487ec681f3Smrg pctx->create_query = agx_create_query; 6497ec681f3Smrg pctx->destroy_query = agx_destroy_query; 6507ec681f3Smrg pctx->begin_query = agx_begin_query; 6517ec681f3Smrg pctx->end_query = agx_end_query; 6527ec681f3Smrg pctx->get_query_result = agx_get_query_result; 6537ec681f3Smrg pctx->set_active_query_state = agx_set_active_query_state; 6547ec681f3Smrg pctx->buffer_map = agx_transfer_map; 6557ec681f3Smrg pctx->texture_map = agx_transfer_map; 6567ec681f3Smrg pctx->transfer_flush_region = agx_transfer_flush_region; 6577ec681f3Smrg pctx->buffer_unmap = agx_transfer_unmap; 6587ec681f3Smrg pctx->texture_unmap = agx_transfer_unmap; 6597ec681f3Smrg pctx->buffer_subdata = u_default_buffer_subdata; 6607ec681f3Smrg pctx->texture_subdata = u_default_texture_subdata; 6617ec681f3Smrg pctx->invalidate_resource = agx_invalidate_resource; 6627ec681f3Smrg agx_init_state_functions(pctx); 6637ec681f3Smrg 6647ec681f3Smrg 6657ec681f3Smrg ctx->blitter = util_blitter_create(pctx); 6667ec681f3Smrg 6677ec681f3Smrg return pctx; 6687ec681f3Smrg} 6697ec681f3Smrg 6707ec681f3Smrgstatic void 6717ec681f3Smrgagx_flush_frontbuffer(struct pipe_screen *_screen, 6727ec681f3Smrg struct pipe_context *pctx, 6737ec681f3Smrg struct pipe_resource *prsrc, 6747ec681f3Smrg unsigned level, unsigned layer, 6757ec681f3Smrg void *context_private, struct pipe_box *box) 6767ec681f3Smrg{ 6777ec681f3Smrg struct agx_resource *rsrc = (struct agx_resource *) prsrc; 6787ec681f3Smrg struct agx_screen *agx_screen = (struct agx_screen*)_screen; 6797ec681f3Smrg struct sw_winsys *winsys = agx_screen->winsys; 6807ec681f3Smrg 6817ec681f3Smrg /* Dump the framebuffer */ 6827ec681f3Smrg assert (rsrc->dt); 6837ec681f3Smrg void *map = winsys->displaytarget_map(winsys, rsrc->dt, PIPE_USAGE_DEFAULT); 6847ec681f3Smrg assert(map != NULL); 6857ec681f3Smrg 6867ec681f3Smrg if (rsrc->modifier == DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER) { 6877ec681f3Smrg agx_detile(rsrc->bo->ptr.cpu, map, 6887ec681f3Smrg rsrc->base.width0, 32, rsrc->dt_stride / 4, 6897ec681f3Smrg 0, 0, rsrc->base.width0, rsrc->base.height0); 6907ec681f3Smrg } else { 6917ec681f3Smrg memcpy(map, rsrc->bo->ptr.cpu, rsrc->dt_stride * rsrc->base.height0); 6927ec681f3Smrg } 6937ec681f3Smrg 6947ec681f3Smrg winsys->displaytarget_display(winsys, rsrc->dt, context_private, box); 6957ec681f3Smrg} 6967ec681f3Smrg 6977ec681f3Smrgstatic const char * 6987ec681f3Smrgagx_get_vendor(struct pipe_screen* pscreen) 6997ec681f3Smrg{ 7007ec681f3Smrg return "Asahi"; 7017ec681f3Smrg} 7027ec681f3Smrg 7037ec681f3Smrgstatic const char * 7047ec681f3Smrgagx_get_device_vendor(struct pipe_screen* pscreen) 7057ec681f3Smrg{ 7067ec681f3Smrg return "Apple"; 7077ec681f3Smrg} 7087ec681f3Smrg 7097ec681f3Smrgstatic const char * 7107ec681f3Smrgagx_get_name(struct pipe_screen* pscreen) 7117ec681f3Smrg{ 7127ec681f3Smrg return "Apple M1 (G13G B0)"; 7137ec681f3Smrg} 7147ec681f3Smrg 7157ec681f3Smrgstatic int 7167ec681f3Smrgagx_get_param(struct pipe_screen* pscreen, enum pipe_cap param) 7177ec681f3Smrg{ 7187ec681f3Smrg bool is_deqp = agx_device(pscreen)->debug & AGX_DBG_DEQP; 7197ec681f3Smrg 7207ec681f3Smrg switch (param) { 7217ec681f3Smrg case PIPE_CAP_NPOT_TEXTURES: 7227ec681f3Smrg case PIPE_CAP_MIXED_COLOR_DEPTH_BITS: 7237ec681f3Smrg case PIPE_CAP_FRAGMENT_SHADER_TEXTURE_LOD: 7247ec681f3Smrg case PIPE_CAP_VERTEX_SHADER_SATURATE: 7257ec681f3Smrg case PIPE_CAP_VERTEX_COLOR_UNCLAMPED: 7267ec681f3Smrg case PIPE_CAP_DEPTH_CLIP_DISABLE: 7277ec681f3Smrg case PIPE_CAP_MIXED_COLORBUFFER_FORMATS: 7287ec681f3Smrg case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES: 7297ec681f3Smrg case PIPE_CAP_FRAGMENT_SHADER_DERIVATIVES: 7307ec681f3Smrg case PIPE_CAP_FRAMEBUFFER_NO_ATTACHMENT: 7317ec681f3Smrg case PIPE_CAP_CLIP_HALFZ: 7327ec681f3Smrg return 1; 7337ec681f3Smrg 7347ec681f3Smrg case PIPE_CAP_MAX_RENDER_TARGETS: 7357ec681f3Smrg return 1; 7367ec681f3Smrg 7377ec681f3Smrg case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS: 7387ec681f3Smrg return 0; 7397ec681f3Smrg 7407ec681f3Smrg case PIPE_CAP_OCCLUSION_QUERY: 7417ec681f3Smrg case PIPE_CAP_PRIMITIVE_RESTART: 7427ec681f3Smrg case PIPE_CAP_PRIMITIVE_RESTART_FIXED_INDEX: 7437ec681f3Smrg return true; 7447ec681f3Smrg 7457ec681f3Smrg case PIPE_CAP_SAMPLER_VIEW_TARGET: 7467ec681f3Smrg case PIPE_CAP_TEXTURE_SWIZZLE: 7477ec681f3Smrg case PIPE_CAP_BLEND_EQUATION_SEPARATE: 7487ec681f3Smrg case PIPE_CAP_INDEP_BLEND_ENABLE: 7497ec681f3Smrg case PIPE_CAP_INDEP_BLEND_FUNC: 7507ec681f3Smrg case PIPE_CAP_ACCELERATED: 7517ec681f3Smrg case PIPE_CAP_UMA: 7527ec681f3Smrg case PIPE_CAP_TEXTURE_FLOAT_LINEAR: 7537ec681f3Smrg case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR: 7547ec681f3Smrg case PIPE_CAP_TGSI_ARRAY_COMPONENTS: 7557ec681f3Smrg case PIPE_CAP_CS_DERIVED_SYSTEM_VALUES_SUPPORTED: 7567ec681f3Smrg case PIPE_CAP_PACKED_UNIFORMS: 7577ec681f3Smrg return 1; 7587ec681f3Smrg 7597ec681f3Smrg case PIPE_CAP_TGSI_INSTANCEID: 7607ec681f3Smrg case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR: 7617ec681f3Smrg case PIPE_CAP_TEXTURE_MULTISAMPLE: 7627ec681f3Smrg case PIPE_CAP_SURFACE_SAMPLE_COUNT: 7637ec681f3Smrg return is_deqp; 7647ec681f3Smrg 7657ec681f3Smrg case PIPE_CAP_COPY_BETWEEN_COMPRESSED_AND_PLAIN_FORMATS: 7667ec681f3Smrg return 0; 7677ec681f3Smrg 7687ec681f3Smrg case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS: 7697ec681f3Smrg return is_deqp ? PIPE_MAX_SO_BUFFERS : 0; 7707ec681f3Smrg 7717ec681f3Smrg case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS: 7727ec681f3Smrg case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS: 7737ec681f3Smrg return is_deqp ? PIPE_MAX_SO_OUTPUTS : 0; 7747ec681f3Smrg 7757ec681f3Smrg case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME: 7767ec681f3Smrg case PIPE_CAP_STREAM_OUTPUT_INTERLEAVE_BUFFERS: 7777ec681f3Smrg return is_deqp ? 1 : 0; 7787ec681f3Smrg 7797ec681f3Smrg case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS: 7807ec681f3Smrg return is_deqp ? 256 : 0; 7817ec681f3Smrg 7827ec681f3Smrg case PIPE_CAP_GLSL_FEATURE_LEVEL: 7837ec681f3Smrg case PIPE_CAP_GLSL_FEATURE_LEVEL_COMPATIBILITY: 7847ec681f3Smrg return 130; 7857ec681f3Smrg case PIPE_CAP_ESSL_FEATURE_LEVEL: 7867ec681f3Smrg return 120; 7877ec681f3Smrg 7887ec681f3Smrg case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT: 7897ec681f3Smrg return 16; 7907ec681f3Smrg 7917ec681f3Smrg case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE: 7927ec681f3Smrg return 65536; 7937ec681f3Smrg 7947ec681f3Smrg case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT: 7957ec681f3Smrg return 64; 7967ec681f3Smrg 7977ec681f3Smrg case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY: 7987ec681f3Smrg return 1; 7997ec681f3Smrg 8007ec681f3Smrg case PIPE_CAP_MAX_TEXTURE_2D_SIZE: 8017ec681f3Smrg return 16384; 8027ec681f3Smrg case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: 8037ec681f3Smrg case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: 8047ec681f3Smrg return 13; 8057ec681f3Smrg 8067ec681f3Smrg case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: 8077ec681f3Smrg return 0; 8087ec681f3Smrg 8097ec681f3Smrg case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: 8107ec681f3Smrg case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: 8117ec681f3Smrg case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: 8127ec681f3Smrg case PIPE_CAP_TGSI_TEXCOORD: 8137ec681f3Smrg case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL: 8147ec681f3Smrg case PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL: 8157ec681f3Smrg case PIPE_CAP_SEAMLESS_CUBE_MAP: 8167ec681f3Smrg case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE: 8177ec681f3Smrg return true; 8187ec681f3Smrg case PIPE_CAP_TGSI_FS_POINT_IS_SYSVAL: 8197ec681f3Smrg return false; 8207ec681f3Smrg 8217ec681f3Smrg case PIPE_CAP_MAX_VERTEX_ELEMENT_SRC_OFFSET: 8227ec681f3Smrg return 0xffff; 8237ec681f3Smrg 8247ec681f3Smrg case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER: 8257ec681f3Smrg return 0; 8267ec681f3Smrg 8277ec681f3Smrg case PIPE_CAP_ENDIANNESS: 8287ec681f3Smrg return PIPE_ENDIAN_LITTLE; 8297ec681f3Smrg 8307ec681f3Smrg case PIPE_CAP_VIDEO_MEMORY: { 8317ec681f3Smrg uint64_t system_memory; 8327ec681f3Smrg 8337ec681f3Smrg if (!os_get_total_physical_memory(&system_memory)) 8347ec681f3Smrg return 0; 8357ec681f3Smrg 8367ec681f3Smrg return (int)(system_memory >> 20); 8377ec681f3Smrg } 8387ec681f3Smrg 8397ec681f3Smrg case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT: 8407ec681f3Smrg return 4; 8417ec681f3Smrg 8427ec681f3Smrg case PIPE_CAP_MAX_VARYINGS: 8437ec681f3Smrg return 16; 8447ec681f3Smrg 8457ec681f3Smrg case PIPE_CAP_FLATSHADE: 8467ec681f3Smrg case PIPE_CAP_TWO_SIDED_COLOR: 8477ec681f3Smrg case PIPE_CAP_ALPHA_TEST: 8487ec681f3Smrg case PIPE_CAP_CLIP_PLANES: 8497ec681f3Smrg case PIPE_CAP_NIR_IMAGES_AS_DEREF: 8507ec681f3Smrg return 0; 8517ec681f3Smrg 8527ec681f3Smrg case PIPE_CAP_SHAREABLE_SHADERS: 8537ec681f3Smrg return 1; 8547ec681f3Smrg 8557ec681f3Smrg default: 8567ec681f3Smrg return u_pipe_screen_get_param_defaults(pscreen, param); 8577ec681f3Smrg } 8587ec681f3Smrg} 8597ec681f3Smrg 8607ec681f3Smrgstatic float 8617ec681f3Smrgagx_get_paramf(struct pipe_screen* pscreen, 8627ec681f3Smrg enum pipe_capf param) 8637ec681f3Smrg{ 8647ec681f3Smrg switch (param) { 8657ec681f3Smrg case PIPE_CAPF_MAX_LINE_WIDTH: 8667ec681f3Smrg case PIPE_CAPF_MAX_LINE_WIDTH_AA: 8677ec681f3Smrg return 16.0; /* Off-by-one fixed point 4:4 encoding */ 8687ec681f3Smrg 8697ec681f3Smrg case PIPE_CAPF_MAX_POINT_WIDTH: 8707ec681f3Smrg case PIPE_CAPF_MAX_POINT_WIDTH_AA: 8717ec681f3Smrg return 511.95f; 8727ec681f3Smrg 8737ec681f3Smrg case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY: 8747ec681f3Smrg return 16.0; 8757ec681f3Smrg 8767ec681f3Smrg case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS: 8777ec681f3Smrg return 16.0; /* arbitrary */ 8787ec681f3Smrg 8797ec681f3Smrg case PIPE_CAPF_MIN_CONSERVATIVE_RASTER_DILATE: 8807ec681f3Smrg case PIPE_CAPF_MAX_CONSERVATIVE_RASTER_DILATE: 8817ec681f3Smrg case PIPE_CAPF_CONSERVATIVE_RASTER_DILATE_GRANULARITY: 8827ec681f3Smrg return 0.0f; 8837ec681f3Smrg 8847ec681f3Smrg default: 8857ec681f3Smrg debug_printf("Unexpected PIPE_CAPF %d query\n", param); 8867ec681f3Smrg return 0.0; 8877ec681f3Smrg } 8887ec681f3Smrg} 8897ec681f3Smrg 8907ec681f3Smrgstatic int 8917ec681f3Smrgagx_get_shader_param(struct pipe_screen* pscreen, 8927ec681f3Smrg enum pipe_shader_type shader, 8937ec681f3Smrg enum pipe_shader_cap param) 8947ec681f3Smrg{ 8957ec681f3Smrg bool is_deqp = agx_device(pscreen)->debug & AGX_DBG_DEQP; 8967ec681f3Smrg bool is_no16 = agx_device(pscreen)->debug & AGX_DBG_NO16; 8977ec681f3Smrg 8987ec681f3Smrg if (shader != PIPE_SHADER_VERTEX && 8997ec681f3Smrg shader != PIPE_SHADER_FRAGMENT) 9007ec681f3Smrg return 0; 9017ec681f3Smrg 9027ec681f3Smrg /* this is probably not totally correct.. but it's a start: */ 9037ec681f3Smrg switch (param) { 9047ec681f3Smrg case PIPE_SHADER_CAP_MAX_INSTRUCTIONS: 9057ec681f3Smrg case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS: 9067ec681f3Smrg case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS: 9077ec681f3Smrg case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS: 9087ec681f3Smrg return 16384; 9097ec681f3Smrg 9107ec681f3Smrg case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH: 9117ec681f3Smrg return 1024; 9127ec681f3Smrg 9137ec681f3Smrg case PIPE_SHADER_CAP_MAX_INPUTS: 9147ec681f3Smrg return 16; 9157ec681f3Smrg 9167ec681f3Smrg case PIPE_SHADER_CAP_MAX_OUTPUTS: 9177ec681f3Smrg return shader == PIPE_SHADER_FRAGMENT ? 4 : 16; 9187ec681f3Smrg 9197ec681f3Smrg case PIPE_SHADER_CAP_MAX_TEMPS: 9207ec681f3Smrg return 256; /* GL_MAX_PROGRAM_TEMPORARIES_ARB */ 9217ec681f3Smrg 9227ec681f3Smrg case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE: 9237ec681f3Smrg return 16 * 1024 * sizeof(float); 9247ec681f3Smrg 9257ec681f3Smrg case PIPE_SHADER_CAP_MAX_CONST_BUFFERS: 9267ec681f3Smrg return 16; 9277ec681f3Smrg 9287ec681f3Smrg case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED: 9297ec681f3Smrg return 0; 9307ec681f3Smrg 9317ec681f3Smrg case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR: 9327ec681f3Smrg case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR: 9337ec681f3Smrg case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR: 9347ec681f3Smrg case PIPE_SHADER_CAP_SUBROUTINES: 9357ec681f3Smrg case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED: 9367ec681f3Smrg return 0; 9377ec681f3Smrg 9387ec681f3Smrg case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR: 9397ec681f3Smrg return is_deqp; 9407ec681f3Smrg 9417ec681f3Smrg case PIPE_SHADER_CAP_INTEGERS: 9427ec681f3Smrg return true; 9437ec681f3Smrg 9447ec681f3Smrg case PIPE_SHADER_CAP_FP16: 9457ec681f3Smrg case PIPE_SHADER_CAP_GLSL_16BIT_CONSTS: 9467ec681f3Smrg case PIPE_SHADER_CAP_FP16_DERIVATIVES: 9477ec681f3Smrg case PIPE_SHADER_CAP_FP16_CONST_BUFFERS: 9487ec681f3Smrg case PIPE_SHADER_CAP_INT16: 9497ec681f3Smrg return !is_no16; 9507ec681f3Smrg 9517ec681f3Smrg case PIPE_SHADER_CAP_INT64_ATOMICS: 9527ec681f3Smrg case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED: 9537ec681f3Smrg case PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED: 9547ec681f3Smrg case PIPE_SHADER_CAP_TGSI_LDEXP_SUPPORTED: 9557ec681f3Smrg case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED: 9567ec681f3Smrg case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE: 9577ec681f3Smrg return 0; 9587ec681f3Smrg 9597ec681f3Smrg case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS: 9607ec681f3Smrg case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS: 9617ec681f3Smrg return 16; /* XXX: How many? */ 9627ec681f3Smrg 9637ec681f3Smrg case PIPE_SHADER_CAP_PREFERRED_IR: 9647ec681f3Smrg return PIPE_SHADER_IR_NIR; 9657ec681f3Smrg 9667ec681f3Smrg case PIPE_SHADER_CAP_SUPPORTED_IRS: 9677ec681f3Smrg return (1 << PIPE_SHADER_IR_NIR) | (1 << PIPE_SHADER_IR_NIR_SERIALIZED); 9687ec681f3Smrg 9697ec681f3Smrg case PIPE_SHADER_CAP_MAX_UNROLL_ITERATIONS_HINT: 9707ec681f3Smrg return 32; 9717ec681f3Smrg 9727ec681f3Smrg case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS: 9737ec681f3Smrg case PIPE_SHADER_CAP_MAX_SHADER_IMAGES: 9747ec681f3Smrg case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTERS: 9757ec681f3Smrg case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTER_BUFFERS: 9767ec681f3Smrg case PIPE_SHADER_CAP_TGSI_SKIP_MERGE_REGISTERS: 9777ec681f3Smrg case PIPE_SHADER_CAP_LOWER_IF_THRESHOLD: 9787ec681f3Smrg return 0; 9797ec681f3Smrg 9807ec681f3Smrg default: 9817ec681f3Smrg /* Other params are unknown */ 9827ec681f3Smrg return 0; 9837ec681f3Smrg } 9847ec681f3Smrg 9857ec681f3Smrg return 0; 9867ec681f3Smrg} 9877ec681f3Smrg 9887ec681f3Smrgstatic int 9897ec681f3Smrgagx_get_compute_param(struct pipe_screen *pscreen, 9907ec681f3Smrg enum pipe_shader_ir ir_type, 9917ec681f3Smrg enum pipe_compute_cap param, 9927ec681f3Smrg void *ret) 9937ec681f3Smrg{ 9947ec681f3Smrg return 0; 9957ec681f3Smrg} 9967ec681f3Smrg 9977ec681f3Smrgstatic bool 9987ec681f3Smrgagx_is_format_supported(struct pipe_screen* pscreen, 9997ec681f3Smrg enum pipe_format format, 10007ec681f3Smrg enum pipe_texture_target target, 10017ec681f3Smrg unsigned sample_count, 10027ec681f3Smrg unsigned storage_sample_count, 10037ec681f3Smrg unsigned usage) 10047ec681f3Smrg{ 10057ec681f3Smrg const struct util_format_description *format_desc; 10067ec681f3Smrg 10077ec681f3Smrg assert(target == PIPE_BUFFER || 10087ec681f3Smrg target == PIPE_TEXTURE_1D || 10097ec681f3Smrg target == PIPE_TEXTURE_1D_ARRAY || 10107ec681f3Smrg target == PIPE_TEXTURE_2D || 10117ec681f3Smrg target == PIPE_TEXTURE_2D_ARRAY || 10127ec681f3Smrg target == PIPE_TEXTURE_RECT || 10137ec681f3Smrg target == PIPE_TEXTURE_3D || 10147ec681f3Smrg target == PIPE_TEXTURE_CUBE || 10157ec681f3Smrg target == PIPE_TEXTURE_CUBE_ARRAY); 10167ec681f3Smrg 10177ec681f3Smrg format_desc = util_format_description(format); 10187ec681f3Smrg 10197ec681f3Smrg if (!format_desc) 10207ec681f3Smrg return false; 10217ec681f3Smrg 10227ec681f3Smrg if (sample_count > 1) 10237ec681f3Smrg return false; 10247ec681f3Smrg 10257ec681f3Smrg if (MAX2(sample_count, 1) != MAX2(storage_sample_count, 1)) 10267ec681f3Smrg return false; 10277ec681f3Smrg 10287ec681f3Smrg if (usage & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW)) { 10297ec681f3Smrg struct agx_pixel_format_entry ent = agx_pixel_format[format]; 10307ec681f3Smrg 10317ec681f3Smrg if (!agx_is_valid_pixel_format(format)) 10327ec681f3Smrg return false; 10337ec681f3Smrg 10347ec681f3Smrg if ((usage & PIPE_BIND_RENDER_TARGET) && !ent.renderable) 10357ec681f3Smrg return false; 10367ec681f3Smrg } 10377ec681f3Smrg 10387ec681f3Smrg /* TODO: formats */ 10397ec681f3Smrg if (usage & PIPE_BIND_VERTEX_BUFFER) { 10407ec681f3Smrg switch (format) { 10417ec681f3Smrg case PIPE_FORMAT_R16_FLOAT: 10427ec681f3Smrg case PIPE_FORMAT_R16G16_FLOAT: 10437ec681f3Smrg case PIPE_FORMAT_R16G16B16_FLOAT: 10447ec681f3Smrg case PIPE_FORMAT_R16G16B16A16_FLOAT: 10457ec681f3Smrg case PIPE_FORMAT_R32_FLOAT: 10467ec681f3Smrg case PIPE_FORMAT_R32G32_FLOAT: 10477ec681f3Smrg case PIPE_FORMAT_R32G32B32_FLOAT: 10487ec681f3Smrg case PIPE_FORMAT_R32G32B32A32_FLOAT: 10497ec681f3Smrg return true; 10507ec681f3Smrg default: 10517ec681f3Smrg return false; 10527ec681f3Smrg } 10537ec681f3Smrg } 10547ec681f3Smrg 10557ec681f3Smrg /* TODO */ 10567ec681f3Smrg return true; 10577ec681f3Smrg} 10587ec681f3Smrg 10597ec681f3Smrgstatic uint64_t 10607ec681f3Smrgagx_get_timestamp(struct pipe_screen *pscreen) 10617ec681f3Smrg{ 10627ec681f3Smrg return 0; 10637ec681f3Smrg} 10647ec681f3Smrg 10657ec681f3Smrgstatic void 10667ec681f3Smrgagx_destroy_screen(struct pipe_screen *screen) 10677ec681f3Smrg{ 10687ec681f3Smrg agx_close_device(agx_device(screen)); 10697ec681f3Smrg ralloc_free(screen); 10707ec681f3Smrg} 10717ec681f3Smrg 10727ec681f3Smrgstatic void 10737ec681f3Smrgagx_fence_reference(struct pipe_screen *screen, 10747ec681f3Smrg struct pipe_fence_handle **ptr, 10757ec681f3Smrg struct pipe_fence_handle *fence) 10767ec681f3Smrg{ 10777ec681f3Smrg} 10787ec681f3Smrg 10797ec681f3Smrgstatic bool 10807ec681f3Smrgagx_fence_finish(struct pipe_screen *screen, 10817ec681f3Smrg struct pipe_context *ctx, 10827ec681f3Smrg struct pipe_fence_handle *fence, 10837ec681f3Smrg uint64_t timeout) 10847ec681f3Smrg{ 10857ec681f3Smrg return true; 10867ec681f3Smrg} 10877ec681f3Smrg 10887ec681f3Smrgstatic const void * 10897ec681f3Smrgagx_get_compiler_options(struct pipe_screen *pscreen, 10907ec681f3Smrg enum pipe_shader_ir ir, 10917ec681f3Smrg enum pipe_shader_type shader) 10927ec681f3Smrg{ 10937ec681f3Smrg return &agx_nir_options; 10947ec681f3Smrg} 10957ec681f3Smrg 10967ec681f3Smrgstruct pipe_screen * 10977ec681f3Smrgagx_screen_create(struct sw_winsys *winsys) 10987ec681f3Smrg{ 10997ec681f3Smrg struct agx_screen *agx_screen; 11007ec681f3Smrg struct pipe_screen *screen; 11017ec681f3Smrg 11027ec681f3Smrg agx_screen = rzalloc(NULL, struct agx_screen); 11037ec681f3Smrg if (!agx_screen) 11047ec681f3Smrg return NULL; 11057ec681f3Smrg 11067ec681f3Smrg screen = &agx_screen->pscreen; 11077ec681f3Smrg agx_screen->winsys = winsys; 11087ec681f3Smrg 11097ec681f3Smrg /* Set debug before opening */ 11107ec681f3Smrg agx_screen->dev.debug = 11117ec681f3Smrg debug_get_flags_option("ASAHI_MESA_DEBUG", agx_debug_options, 0); 11127ec681f3Smrg 11137ec681f3Smrg /* Try to open an AGX device */ 11147ec681f3Smrg if (!agx_open_device(screen, &agx_screen->dev)) { 11157ec681f3Smrg ralloc_free(agx_screen); 11167ec681f3Smrg return NULL; 11177ec681f3Smrg } 11187ec681f3Smrg 11197ec681f3Smrg screen->destroy = agx_destroy_screen; 11207ec681f3Smrg screen->get_name = agx_get_name; 11217ec681f3Smrg screen->get_vendor = agx_get_vendor; 11227ec681f3Smrg screen->get_device_vendor = agx_get_device_vendor; 11237ec681f3Smrg screen->get_param = agx_get_param; 11247ec681f3Smrg screen->get_shader_param = agx_get_shader_param; 11257ec681f3Smrg screen->get_compute_param = agx_get_compute_param; 11267ec681f3Smrg screen->get_paramf = agx_get_paramf; 11277ec681f3Smrg screen->is_format_supported = agx_is_format_supported; 11287ec681f3Smrg screen->context_create = agx_create_context; 11297ec681f3Smrg screen->resource_create = agx_resource_create; 11307ec681f3Smrg screen->resource_from_handle = agx_resource_from_handle; 11317ec681f3Smrg screen->resource_get_handle = agx_resource_get_handle; 11327ec681f3Smrg screen->resource_destroy = agx_resource_destroy; 11337ec681f3Smrg screen->flush_frontbuffer = agx_flush_frontbuffer; 11347ec681f3Smrg screen->get_timestamp = agx_get_timestamp; 11357ec681f3Smrg screen->fence_reference = agx_fence_reference; 11367ec681f3Smrg screen->fence_finish = agx_fence_finish; 11377ec681f3Smrg screen->get_compiler_options = agx_get_compiler_options; 11387ec681f3Smrg 11397ec681f3Smrg agx_internal_shaders(&agx_screen->dev); 11407ec681f3Smrg 11417ec681f3Smrg return screen; 11427ec681f3Smrg} 1143