Path: blob/21.2-virgl/src/gallium/drivers/asahi/agx_pipe.c
4570 views
/*1* Copyright 2010 Red Hat Inc.2* Copyright 2006 VMware, Inc.3*4* Permission is hereby granted, free of charge, to any person obtaining a5* copy of this software and associated documentation files (the "Software"),6* to deal in the Software without restriction, including without limitation7* on the rights to use, copy, modify, merge, publish, distribute, sub8* license, and/or sell copies of the Software, and to permit persons to whom9* the Software is furnished to do so, subject to the following conditions:10*11* The above copyright notice and this permission notice (including the next12* paragraph) shall be included in all copies or substantial portions of the13* Software.14*15* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL18* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,19* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR20* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE21* USE OR OTHER DEALINGS IN THE SOFTWARE.22*/23#include <stdio.h>24#include <errno.h>25#include "pipe/p_defines.h"26#include "pipe/p_state.h"27#include "pipe/p_context.h"28#include "pipe/p_screen.h"29#include "util/u_memory.h"30#include "util/u_screen.h"31#include "util/u_inlines.h"32#include "util/format/u_format.h"33#include "util/u_upload_mgr.h"34#include "util/half_float.h"35#include "frontend/winsys_handle.h"36#include "frontend/sw_winsys.h"37#include "gallium/auxiliary/util/u_transfer.h"38#include "gallium/auxiliary/util/u_surface.h"39#include "gallium/auxiliary/util/u_framebuffer.h"40#include "agx_public.h"41#include "agx_state.h"42#include "magic.h"43#include "asahi/compiler/agx_compile.h"44#include "asahi/lib/decode.h"45#include "asahi/lib/tiling.h"46#include "asahi/lib/agx_formats.h"4748static const struct debug_named_value agx_debug_options[] = {49{"trace", AGX_DBG_TRACE, "Trace the command stream"},50{"deqp", AGX_DBG_DEQP, "Hacks for dEQP"},51{"no16", AGX_DBG_NO16, "Disable 16-bit support"},52DEBUG_NAMED_VALUE_END53};5455void agx_init_state_functions(struct pipe_context *ctx);5657static struct pipe_query *58agx_create_query(struct pipe_context *ctx, unsigned query_type, unsigned index)59{60struct agx_query *query = CALLOC_STRUCT(agx_query);6162return (struct pipe_query *)query;63}6465static void66agx_destroy_query(struct pipe_context *ctx, struct pipe_query *query)67{68FREE(query);69}7071static bool72agx_begin_query(struct pipe_context *ctx, struct pipe_query *query)73{74return true;75}7677static bool78agx_end_query(struct pipe_context *ctx, struct pipe_query *query)79{80return true;81}8283static bool84agx_get_query_result(struct pipe_context *ctx,85struct pipe_query *query,86bool wait,87union pipe_query_result *vresult)88{89uint64_t *result = (uint64_t*)vresult;9091*result = 0;92return true;93}9495static void96agx_set_active_query_state(struct pipe_context *pipe, bool enable)97{98}99100101/*102* resource103*/104105static struct pipe_resource *106agx_resource_from_handle(struct pipe_screen *pscreen,107const struct pipe_resource *templat,108struct winsys_handle *whandle,109unsigned usage)110{111unreachable("Imports todo");112}113114static bool115agx_resource_get_handle(struct pipe_screen *pscreen,116struct pipe_context *ctx,117struct pipe_resource *pt,118struct winsys_handle *handle,119unsigned usage)120{121unreachable("Handles todo");122}123124static inline bool125agx_is_2d(const struct agx_resource *pres)126{127switch (pres->base.target) {128case PIPE_TEXTURE_2D:129case PIPE_TEXTURE_RECT:130return true;131default:132return false;133}134}135136static bool137agx_should_tile(struct agx_device *dev,138const struct agx_resource *pres)139{140const unsigned valid_binding =141PIPE_BIND_DEPTH_STENCIL |142PIPE_BIND_RENDER_TARGET |143PIPE_BIND_BLENDABLE |144PIPE_BIND_SAMPLER_VIEW |145PIPE_BIND_DISPLAY_TARGET |146PIPE_BIND_SCANOUT |147PIPE_BIND_SHARED;148149unsigned bpp = util_format_get_blocksizebits(pres->base.format);150151bool can_tile = agx_is_2d(pres)152&& (bpp == 32)153&& ((pres->base.bind & ~valid_binding) == 0);154155return can_tile && (pres->base.usage != PIPE_USAGE_STREAM);156}157158static struct pipe_resource *159agx_resource_create(struct pipe_screen *screen,160const struct pipe_resource *templ)161{162struct agx_device *dev = agx_device(screen);163struct agx_resource *nresource;164165nresource = CALLOC_STRUCT(agx_resource);166if (!nresource)167return NULL;168169nresource->base = *templ;170nresource->base.screen = screen;171172nresource->modifier =173agx_should_tile(dev, nresource) ?174DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER :175DRM_FORMAT_MOD_LINEAR;176177unsigned offset = 0;178179for (unsigned l = 0; l <= templ->last_level; ++l) {180unsigned width = u_minify(templ->width0, l);181unsigned height = u_minify(templ->height0, l);182183if (nresource->modifier == DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER) {184width = ALIGN_POT(width, 64);185height = ALIGN_POT(height, 64);186}187188nresource->slices[l].line_stride =189util_format_get_stride(templ->format, width);190191nresource->slices[l].offset = offset;192offset += ALIGN_POT(nresource->slices[l].line_stride * height, 0x80);193}194195pipe_reference_init(&nresource->base.reference, 1);196197struct sw_winsys *winsys = ((struct agx_screen *) screen)->winsys;198199if (templ->bind & (PIPE_BIND_DISPLAY_TARGET |200PIPE_BIND_SCANOUT |201PIPE_BIND_SHARED)) {202unsigned width0 = templ->width0, height0 = templ->height0;203204if (nresource->modifier == DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER) {205width0 = ALIGN_POT(width0, 64);206height0 = ALIGN_POT(height0, 64);207}208209nresource->dt = winsys->displaytarget_create(winsys,210templ->bind,211templ->format,212width0,213height0,21464,215NULL /*map_front_private*/,216&nresource->dt_stride);217218nresource->slices[0].line_stride = nresource->dt_stride;219assert((nresource->dt_stride & 0xF) == 0);220221offset = nresource->slices[0].line_stride * ALIGN_POT(templ->height0, 64);222223if (nresource->dt == NULL) {224FREE(nresource);225return NULL;226}227}228229unsigned size = ALIGN_POT(offset, 4096);230nresource->bo = agx_bo_create(dev, size, AGX_MEMORY_TYPE_FRAMEBUFFER);231232if (!nresource->bo) {233FREE(nresource);234return NULL;235}236237return &nresource->base;238}239240static void241agx_resource_destroy(struct pipe_screen *screen,242struct pipe_resource *prsrc)243{244struct agx_resource *rsrc = (struct agx_resource *)prsrc;245246if (rsrc->dt) {247/* display target */248struct agx_screen *agx_screen = (struct agx_screen*)screen;249struct sw_winsys *winsys = agx_screen->winsys;250winsys->displaytarget_destroy(winsys, rsrc->dt);251}252253agx_bo_unreference(rsrc->bo);254FREE(rsrc);255}256257258/*259* transfer260*/261262static void263agx_transfer_flush_region(struct pipe_context *pipe,264struct pipe_transfer *transfer,265const struct pipe_box *box)266{267}268269static void *270agx_transfer_map(struct pipe_context *pctx,271struct pipe_resource *resource,272unsigned level,273unsigned usage, /* a combination of PIPE_MAP_x */274const struct pipe_box *box,275struct pipe_transfer **out_transfer)276{277struct agx_context *ctx = agx_context(pctx);278struct agx_resource *rsrc = agx_resource(resource);279unsigned bytes_per_pixel = util_format_get_blocksize(resource->format);280struct agx_bo *bo = rsrc->bo;281282/* Can't map tiled/compressed directly */283if ((usage & PIPE_MAP_DIRECTLY) && rsrc->modifier != DRM_FORMAT_MOD_LINEAR)284return NULL;285286if (ctx->batch->cbufs[0] && resource == ctx->batch->cbufs[0]->texture)287pctx->flush(pctx, NULL, 0);288if (ctx->batch->zsbuf && resource == ctx->batch->zsbuf->texture)289pctx->flush(pctx, NULL, 0);290291struct agx_transfer *transfer = CALLOC_STRUCT(agx_transfer);292transfer->base.level = level;293transfer->base.usage = usage;294transfer->base.box = *box;295296pipe_resource_reference(&transfer->base.resource, resource);297*out_transfer = &transfer->base;298299if (rsrc->modifier == DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER) {300transfer->base.stride = box->width * bytes_per_pixel;301transfer->base.layer_stride = transfer->base.stride * box->height;302transfer->map = calloc(transfer->base.layer_stride, box->depth);303assert(box->depth == 1);304305if ((usage & PIPE_MAP_READ) && BITSET_TEST(rsrc->data_valid, level)) {306agx_detile(307((uint8_t *) bo->ptr.cpu) + rsrc->slices[level].offset,308transfer->map,309u_minify(resource->width0, level), bytes_per_pixel * 8,310transfer->base.stride / bytes_per_pixel,311box->x, box->y, box->x + box->width, box->y + box->height);312}313314return transfer->map;315} else {316assert (rsrc->modifier == DRM_FORMAT_MOD_LINEAR);317318transfer->base.stride = rsrc->slices[level].line_stride;319transfer->base.layer_stride = 0; // TODO320321/* Be conservative for direct writes */322323if ((usage & PIPE_MAP_WRITE) && (usage & PIPE_MAP_DIRECTLY))324BITSET_SET(rsrc->data_valid, level);325326return ((uint8_t *) bo->ptr.cpu)327+ rsrc->slices[level].offset328+ transfer->base.box.z * transfer->base.layer_stride329+ transfer->base.box.y * rsrc->slices[level].line_stride330+ transfer->base.box.x * bytes_per_pixel;331}332}333334static void335agx_transfer_unmap(struct pipe_context *pctx,336struct pipe_transfer *transfer)337{338/* Gallium expects writeback here, so we tile */339340struct agx_transfer *trans = agx_transfer(transfer);341struct pipe_resource *prsrc = transfer->resource;342struct agx_resource *rsrc = (struct agx_resource *) prsrc;343unsigned bytes_per_pixel = util_format_get_blocksize(prsrc->format);344345if (transfer->usage & PIPE_MAP_WRITE)346BITSET_SET(rsrc->data_valid, transfer->level);347348/* Tiling will occur in software from a staging cpu buffer */349if ((transfer->usage & PIPE_MAP_WRITE) &&350rsrc->modifier == DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER) {351struct agx_bo *bo = rsrc->bo;352assert(trans->map != NULL);353assert(transfer->box.depth == 1);354355agx_tile(356((uint8_t *) bo->ptr.cpu) + rsrc->slices[transfer->level].offset,357trans->map,358u_minify(transfer->resource->width0, transfer->level),359bytes_per_pixel * 8,360transfer->stride / bytes_per_pixel,361transfer->box.x, transfer->box.y,362transfer->box.x + transfer->box.width,363transfer->box.y + transfer->box.height);364}365366/* Free the transfer */367free(trans->map);368pipe_resource_reference(&transfer->resource, NULL);369FREE(transfer);370}371372/*373* clear/copy374*/375static void376agx_clear(struct pipe_context *pctx, unsigned buffers, const struct pipe_scissor_state *scissor_state,377const union pipe_color_union *color, double depth, unsigned stencil)378{379struct agx_context *ctx = agx_context(pctx);380ctx->batch->clear |= buffers;381memcpy(ctx->batch->clear_color, color->f, sizeof(color->f));382}383384385static void386agx_flush_resource(struct pipe_context *ctx,387struct pipe_resource *resource)388{389}390391/*392* context393*/394static void395agx_flush(struct pipe_context *pctx,396struct pipe_fence_handle **fence,397unsigned flags)398{399struct agx_context *ctx = agx_context(pctx);400401if (fence)402*fence = NULL;403404/* TODO */405if (!ctx->batch->cbufs[0])406return;407408/* Nothing to do */409if (!(ctx->batch->draw | ctx->batch->clear))410return;411412/* Finalize the encoder */413uint8_t stop[5 + 64] = { 0x00, 0x00, 0x00, 0xc0, 0x00 };414memcpy(ctx->batch->encoder_current, stop, sizeof(stop));415416/* Emit the commandbuffer */417uint64_t pipeline_clear = 0;418bool clear_pipeline_textures = false;419420struct agx_device *dev = agx_device(pctx->screen);421422if (ctx->batch->clear & PIPE_CLEAR_COLOR0) {423uint16_t clear_colour[4] = {424_mesa_float_to_half(ctx->batch->clear_color[0]),425_mesa_float_to_half(ctx->batch->clear_color[1]),426_mesa_float_to_half(ctx->batch->clear_color[2]),427_mesa_float_to_half(ctx->batch->clear_color[3])428};429430431pipeline_clear = agx_build_clear_pipeline(ctx,432dev->internal.clear,433agx_pool_upload(&ctx->batch->pool, clear_colour, sizeof(clear_colour)));434} else {435enum pipe_format fmt = ctx->batch->cbufs[0]->format;436enum agx_format internal = agx_pixel_format[fmt].internal;437uint32_t shader = dev->reload.format[internal];438439pipeline_clear = agx_build_reload_pipeline(ctx, shader,440ctx->batch->cbufs[0]);441442clear_pipeline_textures = true;443}444445uint64_t pipeline_store =446agx_build_store_pipeline(ctx,447dev->internal.store,448agx_pool_upload(&ctx->batch->pool, ctx->render_target[0], sizeof(ctx->render_target)));449450/* Pipelines must 64 aligned */451struct agx_ptr pipeline_null =452agx_pool_alloc_aligned(&ctx->batch->pipeline_pool, 64, 64);453memset(pipeline_null.cpu, 0, 64);454455struct agx_resource *rt0 = agx_resource(ctx->batch->cbufs[0]->texture);456BITSET_SET(rt0->data_valid, 0);457458struct agx_resource *zbuf = ctx->batch->zsbuf ?459agx_resource(ctx->batch->zsbuf->texture) : NULL;460461if (zbuf)462BITSET_SET(zbuf->data_valid, 0);463464/* BO list for a given batch consists of:465* - BOs for the batch's framebuffer surfaces466* - BOs for the batch's pools467* - BOs for the encoder468* - BO for internal shaders469* - BOs added to the batch explicitly470*/471struct agx_batch *batch = ctx->batch;472473agx_batch_add_bo(batch, batch->encoder);474agx_batch_add_bo(batch, batch->scissor.bo);475agx_batch_add_bo(batch, dev->internal.bo);476agx_batch_add_bo(batch, dev->reload.bo);477478for (unsigned i = 0; i < batch->nr_cbufs; ++i) {479struct pipe_surface *surf = batch->cbufs[i];480assert(surf != NULL && surf->texture != NULL);481struct agx_resource *rsrc = agx_resource(surf->texture);482agx_batch_add_bo(batch, rsrc->bo);483}484485if (batch->zsbuf) {486struct pipe_surface *surf = batch->zsbuf;487struct agx_resource *rsrc = agx_resource(surf->texture);488agx_batch_add_bo(batch, rsrc->bo);489}490491unsigned handle_count =492BITSET_COUNT(batch->bo_list) +493agx_pool_num_bos(&batch->pool) +494agx_pool_num_bos(&batch->pipeline_pool);495496uint32_t *handles = calloc(sizeof(uint32_t), handle_count);497unsigned handle = 0, handle_i = 0;498499BITSET_FOREACH_SET(handle, batch->bo_list, sizeof(batch->bo_list) * 8) {500handles[handle_i++] = handle;501}502503agx_pool_get_bo_handles(&batch->pool, handles + handle_i);504handle_i += agx_pool_num_bos(&batch->pool);505506agx_pool_get_bo_handles(&batch->pipeline_pool, handles + handle_i);507handle_i += agx_pool_num_bos(&batch->pipeline_pool);508509/* Size calculation should've been exact */510assert(handle_i == handle_count);511512unsigned cmdbuf_id = agx_get_global_id(dev);513unsigned encoder_id = agx_get_global_id(dev);514515unsigned cmdbuf_size = demo_cmdbuf(dev->cmdbuf.ptr.cpu,516dev->cmdbuf.size,517&ctx->batch->pool,518ctx->batch->encoder->ptr.gpu,519encoder_id,520ctx->batch->scissor.bo->ptr.gpu,521ctx->batch->width,522ctx->batch->height,523pipeline_null.gpu,524pipeline_clear,525pipeline_store,526rt0->bo->ptr.gpu,527clear_pipeline_textures);528529/* Generate the mapping table from the BO list */530demo_mem_map(dev->memmap.ptr.cpu, dev->memmap.size, handles, handle_count,531cmdbuf_id, encoder_id, cmdbuf_size);532533free(handles);534535agx_submit_cmdbuf(dev, dev->cmdbuf.handle, dev->memmap.handle, dev->queue.id);536537agx_wait_queue(dev->queue);538539if (dev->debug & AGX_DBG_TRACE) {540agxdecode_cmdstream(dev->cmdbuf.handle, dev->memmap.handle, true);541agxdecode_next_frame();542}543544memset(batch->bo_list, 0, sizeof(batch->bo_list));545agx_pool_cleanup(&ctx->batch->pool);546agx_pool_cleanup(&ctx->batch->pipeline_pool);547agx_pool_init(&ctx->batch->pool, dev, AGX_MEMORY_TYPE_FRAMEBUFFER, true);548agx_pool_init(&ctx->batch->pipeline_pool, dev, AGX_MEMORY_TYPE_CMDBUF_32, true);549ctx->batch->clear = 0;550ctx->batch->draw = 0;551ctx->batch->encoder_current = ctx->batch->encoder->ptr.cpu;552ctx->batch->scissor.count = 0;553ctx->dirty = ~0;554}555556static void557agx_destroy_context(struct pipe_context *pctx)558{559struct agx_context *ctx = agx_context(pctx);560561if (pctx->stream_uploader)562u_upload_destroy(pctx->stream_uploader);563564if (ctx->blitter)565util_blitter_destroy(ctx->blitter);566567util_unreference_framebuffer_state(&ctx->framebuffer);568569FREE(ctx);570}571572static void573agx_invalidate_resource(struct pipe_context *ctx,574struct pipe_resource *resource)575{576}577578static struct pipe_context *579agx_create_context(struct pipe_screen *screen,580void *priv, unsigned flags)581{582struct agx_context *ctx = CALLOC_STRUCT(agx_context);583struct pipe_context *pctx = &ctx->base;584585if (!ctx)586return NULL;587588pctx->screen = screen;589pctx->priv = priv;590591ctx->batch = CALLOC_STRUCT(agx_batch);592agx_pool_init(&ctx->batch->pool,593agx_device(screen), AGX_MEMORY_TYPE_FRAMEBUFFER, true);594agx_pool_init(&ctx->batch->pipeline_pool,595agx_device(screen), AGX_MEMORY_TYPE_SHADER, true);596ctx->batch->encoder = agx_bo_create(agx_device(screen), 0x80000, AGX_MEMORY_TYPE_FRAMEBUFFER);597ctx->batch->encoder_current = ctx->batch->encoder->ptr.cpu;598ctx->batch->scissor.bo = agx_bo_create(agx_device(screen), 0x80000, AGX_MEMORY_TYPE_FRAMEBUFFER);599600/* Upload fixed shaders (TODO: compile them?) */601602pctx->stream_uploader = u_upload_create_default(pctx);603if (!pctx->stream_uploader) {604FREE(pctx);605return NULL;606}607pctx->const_uploader = pctx->stream_uploader;608609pctx->destroy = agx_destroy_context;610pctx->flush = agx_flush;611pctx->clear = agx_clear;612pctx->resource_copy_region = util_resource_copy_region;613pctx->blit = agx_blit;614pctx->flush_resource = agx_flush_resource;615pctx->create_query = agx_create_query;616pctx->destroy_query = agx_destroy_query;617pctx->begin_query = agx_begin_query;618pctx->end_query = agx_end_query;619pctx->get_query_result = agx_get_query_result;620pctx->set_active_query_state = agx_set_active_query_state;621pctx->buffer_map = agx_transfer_map;622pctx->texture_map = agx_transfer_map;623pctx->transfer_flush_region = agx_transfer_flush_region;624pctx->buffer_unmap = agx_transfer_unmap;625pctx->texture_unmap = agx_transfer_unmap;626pctx->buffer_subdata = u_default_buffer_subdata;627pctx->texture_subdata = u_default_texture_subdata;628pctx->invalidate_resource = agx_invalidate_resource;629agx_init_state_functions(pctx);630631632ctx->blitter = util_blitter_create(pctx);633634return pctx;635}636637static void638agx_flush_frontbuffer(struct pipe_screen *_screen,639struct pipe_context *pctx,640struct pipe_resource *prsrc,641unsigned level, unsigned layer,642void *context_private, struct pipe_box *box)643{644struct agx_resource *rsrc = (struct agx_resource *) prsrc;645struct agx_screen *agx_screen = (struct agx_screen*)_screen;646struct sw_winsys *winsys = agx_screen->winsys;647648/* Dump the framebuffer */649assert (rsrc->dt);650void *map = winsys->displaytarget_map(winsys, rsrc->dt, PIPE_USAGE_DEFAULT);651assert(map != NULL);652653if (rsrc->modifier == DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER) {654agx_detile(rsrc->bo->ptr.cpu, map,655rsrc->base.width0, 32, rsrc->dt_stride / 4,6560, 0, rsrc->base.width0, rsrc->base.height0);657} else {658memcpy(map, rsrc->bo->ptr.cpu, rsrc->dt_stride * rsrc->base.height0);659}660661winsys->displaytarget_display(winsys, rsrc->dt, context_private, box);662}663664static const char *665agx_get_vendor(struct pipe_screen* pscreen)666{667return "Asahi";668}669670static const char *671agx_get_device_vendor(struct pipe_screen* pscreen)672{673return "Apple";674}675676static const char *677agx_get_name(struct pipe_screen* pscreen)678{679return "Apple M1 (G13G B0)";680}681682static int683agx_get_param(struct pipe_screen* pscreen, enum pipe_cap param)684{685bool is_deqp = agx_device(pscreen)->debug & AGX_DBG_DEQP;686687switch (param) {688case PIPE_CAP_NPOT_TEXTURES:689case PIPE_CAP_MIXED_COLOR_DEPTH_BITS:690case PIPE_CAP_FRAGMENT_SHADER_TEXTURE_LOD:691case PIPE_CAP_VERTEX_SHADER_SATURATE:692case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:693case PIPE_CAP_DEPTH_CLIP_DISABLE:694case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:695case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES:696case PIPE_CAP_FRAGMENT_SHADER_DERIVATIVES:697case PIPE_CAP_FRAMEBUFFER_NO_ATTACHMENT:698case PIPE_CAP_CLIP_HALFZ:699return 1;700701case PIPE_CAP_MAX_RENDER_TARGETS:702return 1;703704case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:705return 0;706707case PIPE_CAP_OCCLUSION_QUERY:708case PIPE_CAP_PRIMITIVE_RESTART:709case PIPE_CAP_PRIMITIVE_RESTART_FIXED_INDEX:710return true;711712case PIPE_CAP_SAMPLER_VIEW_TARGET:713case PIPE_CAP_TEXTURE_SWIZZLE:714case PIPE_CAP_BLEND_EQUATION_SEPARATE:715case PIPE_CAP_INDEP_BLEND_ENABLE:716case PIPE_CAP_INDEP_BLEND_FUNC:717case PIPE_CAP_ACCELERATED:718case PIPE_CAP_UMA:719case PIPE_CAP_TEXTURE_FLOAT_LINEAR:720case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR:721case PIPE_CAP_TGSI_ARRAY_COMPONENTS:722case PIPE_CAP_CS_DERIVED_SYSTEM_VALUES_SUPPORTED:723case PIPE_CAP_PACKED_UNIFORMS:724return 1;725726case PIPE_CAP_TGSI_INSTANCEID:727case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR:728case PIPE_CAP_TEXTURE_MULTISAMPLE:729case PIPE_CAP_SURFACE_SAMPLE_COUNT:730return is_deqp;731732case PIPE_CAP_COPY_BETWEEN_COMPRESSED_AND_PLAIN_FORMATS:733return 0;734735case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:736return is_deqp ? PIPE_MAX_SO_BUFFERS : 0;737738case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS:739case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:740return is_deqp ? PIPE_MAX_SO_OUTPUTS : 0;741742case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:743case PIPE_CAP_STREAM_OUTPUT_INTERLEAVE_BUFFERS:744return is_deqp ? 1 : 0;745746case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:747return is_deqp ? 256 : 0;748749case PIPE_CAP_GLSL_FEATURE_LEVEL:750case PIPE_CAP_GLSL_FEATURE_LEVEL_COMPATIBILITY:751return 130;752case PIPE_CAP_ESSL_FEATURE_LEVEL:753return 120;754755case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:756return 16;757758case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE:759return 65536;760761case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:762return 64;763764case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:765return 1;766767case PIPE_CAP_MAX_TEXTURE_2D_SIZE:768return 16384;769case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:770case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:771return 13;772773case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:774return 0;775776case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:777case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:778case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:779case PIPE_CAP_TGSI_TEXCOORD:780case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL:781case PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL:782case PIPE_CAP_SEAMLESS_CUBE_MAP:783case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:784return true;785case PIPE_CAP_TGSI_FS_POINT_IS_SYSVAL:786return false;787788case PIPE_CAP_MAX_VERTEX_ELEMENT_SRC_OFFSET:789return 0xffff;790791case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:792return 0;793794case PIPE_CAP_ENDIANNESS:795return PIPE_ENDIAN_LITTLE;796797case PIPE_CAP_VIDEO_MEMORY: {798uint64_t system_memory;799800if (!os_get_total_physical_memory(&system_memory))801return 0;802803return (int)(system_memory >> 20);804}805806case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT:807return 4;808809case PIPE_CAP_MAX_VARYINGS:810return 16;811812case PIPE_CAP_FLATSHADE:813case PIPE_CAP_TWO_SIDED_COLOR:814case PIPE_CAP_ALPHA_TEST:815case PIPE_CAP_CLIP_PLANES:816case PIPE_CAP_NIR_IMAGES_AS_DEREF:817return 0;818819case PIPE_CAP_SHAREABLE_SHADERS:820return 1;821822default:823return u_pipe_screen_get_param_defaults(pscreen, param);824}825}826827static float828agx_get_paramf(struct pipe_screen* pscreen,829enum pipe_capf param)830{831switch (param) {832case PIPE_CAPF_MAX_LINE_WIDTH:833case PIPE_CAPF_MAX_LINE_WIDTH_AA:834return 16.0; /* Off-by-one fixed point 4:4 encoding */835836case PIPE_CAPF_MAX_POINT_WIDTH:837case PIPE_CAPF_MAX_POINT_WIDTH_AA:838return 511.95f;839840case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY:841return 16.0;842843case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:844return 16.0; /* arbitrary */845846case PIPE_CAPF_MIN_CONSERVATIVE_RASTER_DILATE:847case PIPE_CAPF_MAX_CONSERVATIVE_RASTER_DILATE:848case PIPE_CAPF_CONSERVATIVE_RASTER_DILATE_GRANULARITY:849return 0.0f;850851default:852debug_printf("Unexpected PIPE_CAPF %d query\n", param);853return 0.0;854}855}856857static int858agx_get_shader_param(struct pipe_screen* pscreen,859enum pipe_shader_type shader,860enum pipe_shader_cap param)861{862bool is_deqp = agx_device(pscreen)->debug & AGX_DBG_DEQP;863bool is_no16 = agx_device(pscreen)->debug & AGX_DBG_NO16;864865if (shader != PIPE_SHADER_VERTEX &&866shader != PIPE_SHADER_FRAGMENT)867return 0;868869/* this is probably not totally correct.. but it's a start: */870switch (param) {871case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:872case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:873case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:874case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:875return 16384;876877case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:878return 1024;879880case PIPE_SHADER_CAP_MAX_INPUTS:881return 16;882883case PIPE_SHADER_CAP_MAX_OUTPUTS:884return shader == PIPE_SHADER_FRAGMENT ? 4 : 16;885886case PIPE_SHADER_CAP_MAX_TEMPS:887return 256; /* GL_MAX_PROGRAM_TEMPORARIES_ARB */888889case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE:890return 16 * 1024 * sizeof(float);891892case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:893return 16;894895case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:896return 0;897898case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:899case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:900case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:901case PIPE_SHADER_CAP_SUBROUTINES:902case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED:903return 0;904905case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:906return is_deqp;907908case PIPE_SHADER_CAP_INTEGERS:909return true;910911case PIPE_SHADER_CAP_FP16:912case PIPE_SHADER_CAP_GLSL_16BIT_CONSTS:913case PIPE_SHADER_CAP_FP16_DERIVATIVES:914case PIPE_SHADER_CAP_FP16_CONST_BUFFERS:915case PIPE_SHADER_CAP_INT16:916return !is_no16;917918case PIPE_SHADER_CAP_INT64_ATOMICS:919case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED:920case PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED:921case PIPE_SHADER_CAP_TGSI_LDEXP_SUPPORTED:922case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED:923case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE:924return 0;925926case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:927case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS:928return 16; /* XXX: How many? */929930case PIPE_SHADER_CAP_PREFERRED_IR:931return PIPE_SHADER_IR_NIR;932933case PIPE_SHADER_CAP_SUPPORTED_IRS:934return (1 << PIPE_SHADER_IR_NIR) | (1 << PIPE_SHADER_IR_NIR_SERIALIZED);935936case PIPE_SHADER_CAP_MAX_UNROLL_ITERATIONS_HINT:937return 32;938939case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS:940case PIPE_SHADER_CAP_MAX_SHADER_IMAGES:941case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTERS:942case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTER_BUFFERS:943case PIPE_SHADER_CAP_TGSI_SKIP_MERGE_REGISTERS:944case PIPE_SHADER_CAP_LOWER_IF_THRESHOLD:945return 0;946947default:948/* Other params are unknown */949return 0;950}951952return 0;953}954955static int956agx_get_compute_param(struct pipe_screen *pscreen,957enum pipe_shader_ir ir_type,958enum pipe_compute_cap param,959void *ret)960{961return 0;962}963964static bool965agx_is_format_supported(struct pipe_screen* pscreen,966enum pipe_format format,967enum pipe_texture_target target,968unsigned sample_count,969unsigned storage_sample_count,970unsigned usage)971{972const struct util_format_description *format_desc;973974assert(target == PIPE_BUFFER ||975target == PIPE_TEXTURE_1D ||976target == PIPE_TEXTURE_1D_ARRAY ||977target == PIPE_TEXTURE_2D ||978target == PIPE_TEXTURE_2D_ARRAY ||979target == PIPE_TEXTURE_RECT ||980target == PIPE_TEXTURE_3D ||981target == PIPE_TEXTURE_CUBE ||982target == PIPE_TEXTURE_CUBE_ARRAY);983984format_desc = util_format_description(format);985986if (!format_desc)987return false;988989if (sample_count > 1)990return false;991992if (MAX2(sample_count, 1) != MAX2(storage_sample_count, 1))993return false;994995if (usage & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW)) {996struct agx_pixel_format_entry ent = agx_pixel_format[format];997998if (!agx_is_valid_pixel_format(format))999return false;10001001if ((usage & PIPE_BIND_RENDER_TARGET) && !ent.renderable)1002return false;1003}10041005/* TODO: formats */1006if (usage & PIPE_BIND_VERTEX_BUFFER) {1007switch (format) {1008case PIPE_FORMAT_R16_FLOAT:1009case PIPE_FORMAT_R16G16_FLOAT:1010case PIPE_FORMAT_R16G16B16_FLOAT:1011case PIPE_FORMAT_R16G16B16A16_FLOAT:1012case PIPE_FORMAT_R32_FLOAT:1013case PIPE_FORMAT_R32G32_FLOAT:1014case PIPE_FORMAT_R32G32B32_FLOAT:1015case PIPE_FORMAT_R32G32B32A32_FLOAT:1016return true;1017default:1018return false;1019}1020}10211022/* TODO */1023return true;1024}10251026static uint64_t1027agx_get_timestamp(struct pipe_screen *pscreen)1028{1029return 0;1030}10311032static void1033agx_destroy_screen(struct pipe_screen *screen)1034{1035agx_close_device(agx_device(screen));1036ralloc_free(screen);1037}10381039static void1040agx_fence_reference(struct pipe_screen *screen,1041struct pipe_fence_handle **ptr,1042struct pipe_fence_handle *fence)1043{1044}10451046static bool1047agx_fence_finish(struct pipe_screen *screen,1048struct pipe_context *ctx,1049struct pipe_fence_handle *fence,1050uint64_t timeout)1051{1052return true;1053}10541055static const void *1056agx_get_compiler_options(struct pipe_screen *pscreen,1057enum pipe_shader_ir ir,1058enum pipe_shader_type shader)1059{1060return &agx_nir_options;1061}10621063struct pipe_screen *1064agx_screen_create(struct sw_winsys *winsys)1065{1066struct agx_screen *agx_screen;1067struct pipe_screen *screen;10681069agx_screen = rzalloc(NULL, struct agx_screen);1070if (!agx_screen)1071return NULL;10721073screen = &agx_screen->pscreen;1074agx_screen->winsys = winsys;10751076/* Set debug before opening */1077agx_screen->dev.debug =1078debug_get_flags_option("ASAHI_MESA_DEBUG", agx_debug_options, 0);10791080/* Try to open an AGX device */1081if (!agx_open_device(screen, &agx_screen->dev)) {1082ralloc_free(agx_screen);1083return NULL;1084}10851086screen->destroy = agx_destroy_screen;1087screen->get_name = agx_get_name;1088screen->get_vendor = agx_get_vendor;1089screen->get_device_vendor = agx_get_device_vendor;1090screen->get_param = agx_get_param;1091screen->get_shader_param = agx_get_shader_param;1092screen->get_compute_param = agx_get_compute_param;1093screen->get_paramf = agx_get_paramf;1094screen->is_format_supported = agx_is_format_supported;1095screen->context_create = agx_create_context;1096screen->resource_create = agx_resource_create;1097screen->resource_from_handle = agx_resource_from_handle;1098screen->resource_get_handle = agx_resource_get_handle;1099screen->resource_destroy = agx_resource_destroy;1100screen->flush_frontbuffer = agx_flush_frontbuffer;1101screen->get_timestamp = agx_get_timestamp;1102screen->fence_reference = agx_fence_reference;1103screen->fence_finish = agx_fence_finish;1104screen->get_compiler_options = agx_get_compiler_options;11051106agx_internal_shaders(&agx_screen->dev);11071108return screen;1109}111011111112