Path: blob/21.2-virgl/src/gallium/auxiliary/driver_ddebug/dd_screen.c
4561 views
/**************************************************************************1*2* Copyright 2015 Advanced Micro Devices, Inc.3* Copyright 2008 VMware, Inc.4* All Rights Reserved.5*6* Permission is hereby granted, free of charge, to any person obtaining a7* copy of this software and associated documentation files (the "Software"),8* to deal in the Software without restriction, including without limitation9* on the rights to use, copy, modify, merge, publish, distribute, sub10* license, and/or sell copies of the Software, and to permit persons to whom11* the Software is furnished to do so, subject to the following conditions:12*13* The above copyright notice and this permission notice (including the next14* paragraph) shall be included in all copies or substantial portions of the15* Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,19* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL20* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,21* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR22* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE23* USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/2627#include "dd_pipe.h"28#include "dd_public.h"29#include "util/u_memory.h"30#include <ctype.h>31#include <stdio.h>323334static const char *35dd_screen_get_name(struct pipe_screen *_screen)36{37struct pipe_screen *screen = dd_screen(_screen)->screen;3839return screen->get_name(screen);40}4142static const char *43dd_screen_get_vendor(struct pipe_screen *_screen)44{45struct pipe_screen *screen = dd_screen(_screen)->screen;4647return screen->get_vendor(screen);48}4950static const char *51dd_screen_get_device_vendor(struct pipe_screen *_screen)52{53struct pipe_screen *screen = dd_screen(_screen)->screen;5455return screen->get_device_vendor(screen);56}5758static const void *59dd_screen_get_compiler_options(struct pipe_screen *_screen,60enum pipe_shader_ir ir,61enum pipe_shader_type shader)62{63struct pipe_screen *screen = dd_screen(_screen)->screen;6465return screen->get_compiler_options(screen, ir, shader);66}6768static struct disk_cache *69dd_screen_get_disk_shader_cache(struct pipe_screen *_screen)70{71struct pipe_screen *screen = dd_screen(_screen)->screen;7273return screen->get_disk_shader_cache(screen);74}7576static int77dd_screen_get_param(struct pipe_screen *_screen,78enum pipe_cap param)79{80struct pipe_screen *screen = dd_screen(_screen)->screen;8182return screen->get_param(screen, param);83}8485static float86dd_screen_get_paramf(struct pipe_screen *_screen,87enum pipe_capf param)88{89struct pipe_screen *screen = dd_screen(_screen)->screen;9091return screen->get_paramf(screen, param);92}9394static int95dd_screen_get_compute_param(struct pipe_screen *_screen,96enum pipe_shader_ir ir_type,97enum pipe_compute_cap param,98void *ret)99{100struct pipe_screen *screen = dd_screen(_screen)->screen;101102return screen->get_compute_param(screen, ir_type, param, ret);103}104105static int106dd_screen_get_shader_param(struct pipe_screen *_screen,107enum pipe_shader_type shader,108enum pipe_shader_cap param)109{110struct pipe_screen *screen = dd_screen(_screen)->screen;111112return screen->get_shader_param(screen, shader, param);113}114115static uint64_t116dd_screen_get_timestamp(struct pipe_screen *_screen)117{118struct pipe_screen *screen = dd_screen(_screen)->screen;119120return screen->get_timestamp(screen);121}122123static void dd_screen_query_memory_info(struct pipe_screen *_screen,124struct pipe_memory_info *info)125{126struct pipe_screen *screen = dd_screen(_screen)->screen;127128screen->query_memory_info(screen, info);129}130131static struct pipe_context *132dd_screen_context_create(struct pipe_screen *_screen, void *priv,133unsigned flags)134{135struct dd_screen *dscreen = dd_screen(_screen);136struct pipe_screen *screen = dscreen->screen;137138flags |= PIPE_CONTEXT_DEBUG;139140return dd_context_create(dscreen,141screen->context_create(screen, priv, flags));142}143144static bool145dd_screen_is_format_supported(struct pipe_screen *_screen,146enum pipe_format format,147enum pipe_texture_target target,148unsigned sample_count,149unsigned storage_sample_count,150unsigned tex_usage)151{152struct pipe_screen *screen = dd_screen(_screen)->screen;153154return screen->is_format_supported(screen, format, target, sample_count,155storage_sample_count, tex_usage);156}157158static bool159dd_screen_can_create_resource(struct pipe_screen *_screen,160const struct pipe_resource *templat)161{162struct pipe_screen *screen = dd_screen(_screen)->screen;163164return screen->can_create_resource(screen, templat);165}166167static void168dd_screen_flush_frontbuffer(struct pipe_screen *_screen,169struct pipe_context *_pipe,170struct pipe_resource *resource,171unsigned level, unsigned layer,172void *context_private,173struct pipe_box *sub_box)174{175struct pipe_screen *screen = dd_screen(_screen)->screen;176struct pipe_context *pipe = _pipe ? dd_context(_pipe)->pipe : NULL;177178screen->flush_frontbuffer(screen, pipe, resource, level, layer, context_private,179sub_box);180}181182static int183dd_screen_get_driver_query_info(struct pipe_screen *_screen,184unsigned index,185struct pipe_driver_query_info *info)186{187struct pipe_screen *screen = dd_screen(_screen)->screen;188189return screen->get_driver_query_info(screen, index, info);190}191192static int193dd_screen_get_driver_query_group_info(struct pipe_screen *_screen,194unsigned index,195struct pipe_driver_query_group_info *info)196{197struct pipe_screen *screen = dd_screen(_screen)->screen;198199return screen->get_driver_query_group_info(screen, index, info);200}201202203static void204dd_screen_get_driver_uuid(struct pipe_screen *_screen, char *uuid)205{206struct pipe_screen *screen = dd_screen(_screen)->screen;207208screen->get_driver_uuid(screen, uuid);209}210211static void212dd_screen_get_device_uuid(struct pipe_screen *_screen, char *uuid)213{214struct pipe_screen *screen = dd_screen(_screen)->screen;215216screen->get_device_uuid(screen, uuid);217}218219/********************************************************************220* resource221*/222223static struct pipe_resource *224dd_screen_resource_create(struct pipe_screen *_screen,225const struct pipe_resource *templat)226{227struct pipe_screen *screen = dd_screen(_screen)->screen;228struct pipe_resource *res = screen->resource_create(screen, templat);229230if (!res)231return NULL;232res->screen = _screen;233return res;234}235236static struct pipe_resource *237dd_screen_resource_from_handle(struct pipe_screen *_screen,238const struct pipe_resource *templ,239struct winsys_handle *handle,240unsigned usage)241{242struct pipe_screen *screen = dd_screen(_screen)->screen;243struct pipe_resource *res =244screen->resource_from_handle(screen, templ, handle, usage);245246if (!res)247return NULL;248res->screen = _screen;249return res;250}251252static struct pipe_resource *253dd_screen_resource_from_user_memory(struct pipe_screen *_screen,254const struct pipe_resource *templ,255void *user_memory)256{257struct pipe_screen *screen = dd_screen(_screen)->screen;258struct pipe_resource *res =259screen->resource_from_user_memory(screen, templ, user_memory);260261if (!res)262return NULL;263res->screen = _screen;264return res;265}266267static struct pipe_resource *268dd_screen_resource_from_memobj(struct pipe_screen *_screen,269const struct pipe_resource *templ,270struct pipe_memory_object *memobj,271uint64_t offset)272{273struct pipe_screen *screen = dd_screen(_screen)->screen;274struct pipe_resource *res =275screen->resource_from_memobj(screen, templ, memobj, offset);276277if (!res)278return NULL;279res->screen = _screen;280return res;281}282283static void284dd_screen_resource_changed(struct pipe_screen *_screen,285struct pipe_resource *res)286{287struct pipe_screen *screen = dd_screen(_screen)->screen;288289if (screen->resource_changed)290screen->resource_changed(screen, res);291}292293static void294dd_screen_resource_destroy(struct pipe_screen *_screen,295struct pipe_resource *res)296{297struct pipe_screen *screen = dd_screen(_screen)->screen;298299screen->resource_destroy(screen, res);300}301302static bool303dd_screen_resource_get_handle(struct pipe_screen *_screen,304struct pipe_context *_pipe,305struct pipe_resource *resource,306struct winsys_handle *handle,307unsigned usage)308{309struct pipe_screen *screen = dd_screen(_screen)->screen;310struct pipe_context *pipe = _pipe ? dd_context(_pipe)->pipe : NULL;311312return screen->resource_get_handle(screen, pipe, resource, handle, usage);313}314315static bool316dd_screen_resource_get_param(struct pipe_screen *_screen,317struct pipe_context *_pipe,318struct pipe_resource *resource,319unsigned plane,320unsigned layer,321unsigned level,322enum pipe_resource_param param,323unsigned handle_usage,324uint64_t *value)325{326struct pipe_screen *screen = dd_screen(_screen)->screen;327struct pipe_context *pipe = _pipe ? dd_context(_pipe)->pipe : NULL;328329return screen->resource_get_param(screen, pipe, resource, plane, layer,330level, param, handle_usage, value);331}332333static void334dd_screen_resource_get_info(struct pipe_screen *_screen,335struct pipe_resource *resource,336unsigned *stride,337unsigned *offset)338{339struct pipe_screen *screen = dd_screen(_screen)->screen;340341screen->resource_get_info(screen, resource, stride, offset);342}343344static bool345dd_screen_check_resource_capability(struct pipe_screen *_screen,346struct pipe_resource *resource,347unsigned bind)348{349struct pipe_screen *screen = dd_screen(_screen)->screen;350351return screen->check_resource_capability(screen, resource, bind);352}353354355/********************************************************************356* fence357*/358359static void360dd_screen_fence_reference(struct pipe_screen *_screen,361struct pipe_fence_handle **pdst,362struct pipe_fence_handle *src)363{364struct pipe_screen *screen = dd_screen(_screen)->screen;365366screen->fence_reference(screen, pdst, src);367}368369static bool370dd_screen_fence_finish(struct pipe_screen *_screen,371struct pipe_context *_ctx,372struct pipe_fence_handle *fence,373uint64_t timeout)374{375struct pipe_screen *screen = dd_screen(_screen)->screen;376struct pipe_context *ctx = _ctx ? dd_context(_ctx)->pipe : NULL;377378return screen->fence_finish(screen, ctx, fence, timeout);379}380381static int382dd_screen_fence_get_fd(struct pipe_screen *_screen,383struct pipe_fence_handle *fence)384{385struct pipe_screen *screen = dd_screen(_screen)->screen;386387return screen->fence_get_fd(screen, fence);388}389390/********************************************************************391* memobj392*/393394static struct pipe_memory_object *395dd_screen_memobj_create_from_handle(struct pipe_screen *_screen,396struct winsys_handle *handle,397bool dedicated)398{399struct pipe_screen *screen = dd_screen(_screen)->screen;400401return screen->memobj_create_from_handle(screen, handle, dedicated);402}403404static void405dd_screen_memobj_destroy(struct pipe_screen *_screen,406struct pipe_memory_object *memobj)407{408struct pipe_screen *screen = dd_screen(_screen)->screen;409410screen->memobj_destroy(screen, memobj);411}412/********************************************************************413* screen414*/415416static void417dd_screen_finalize_nir(struct pipe_screen *_screen, void *nir, bool optimize)418{419struct pipe_screen *screen = dd_screen(_screen)->screen;420421screen->finalize_nir(screen, nir, optimize);422}423424static void425dd_screen_destroy(struct pipe_screen *_screen)426{427struct dd_screen *dscreen = dd_screen(_screen);428struct pipe_screen *screen = dscreen->screen;429430screen->destroy(screen);431FREE(dscreen);432}433434static void435skip_space(const char **p)436{437while (isspace(**p))438(*p)++;439}440441static bool442match_word(const char **cur, const char *word)443{444size_t len = strlen(word);445if (strncmp(*cur, word, len) != 0)446return false;447448const char *p = *cur + len;449if (*p) {450if (!isspace(*p))451return false;452453*cur = p + 1;454} else {455*cur = p;456}457458return true;459}460461static bool462match_uint(const char **cur, unsigned *value)463{464char *end;465unsigned v = strtoul(*cur, &end, 0);466if (end == *cur || (*end && !isspace(*end)))467return false;468*cur = end;469*value = v;470return true;471}472473struct pipe_screen *474ddebug_screen_create(struct pipe_screen *screen)475{476struct dd_screen *dscreen;477const char *option;478bool flush = false;479bool verbose = false;480bool transfers = false;481unsigned timeout = 1000;482unsigned apitrace_dump_call = 0;483enum dd_dump_mode mode = DD_DUMP_ONLY_HANGS;484485option = debug_get_option("GALLIUM_DDEBUG", NULL);486if (!option)487return screen;488489if (!strcmp(option, "help")) {490puts("Gallium driver debugger");491puts("");492puts("Usage:");493puts("");494puts(" GALLIUM_DDEBUG=\"[<timeout in ms>] [(always|apitrace <call#)] [flush] [transfers] [verbose]\"");495puts(" GALLIUM_DDEBUG_SKIP=[count]");496puts("");497puts("Dump context and driver information of draw calls into");498puts("$HOME/"DD_DIR"/. By default, watch for GPU hangs and only dump information");499puts("about draw calls related to the hang.");500puts("");501puts("<timeout in ms>");502puts(" Change the default timeout for GPU hang detection (default=1000ms).");503puts(" Setting this to 0 will disable GPU hang detection entirely.");504puts("");505puts("always");506puts(" Dump information about all draw calls.");507puts("");508puts("transfers");509puts(" Also dump and do hang detection on transfers.");510puts("");511puts("apitrace <call#>");512puts(" Dump information about the draw call corresponding to the given");513puts(" apitrace call number and exit.");514puts("");515puts("flush");516puts(" Flush after every draw call.");517puts("");518puts("verbose");519puts(" Write additional information to stderr.");520puts("");521puts("GALLIUM_DDEBUG_SKIP=count");522puts(" Skip dumping on the first count draw calls (only relevant with 'always').");523puts("");524exit(0);525}526527for (;;) {528skip_space(&option);529if (!*option)530break;531532if (match_word(&option, "always")) {533if (mode == DD_DUMP_APITRACE_CALL) {534printf("ddebug: both 'always' and 'apitrace' specified\n");535exit(1);536}537538mode = DD_DUMP_ALL_CALLS;539} else if (match_word(&option, "flush")) {540flush = true;541} else if (match_word(&option, "transfers")) {542transfers = true;543} else if (match_word(&option, "verbose")) {544verbose = true;545} else if (match_word(&option, "apitrace")) {546if (mode != DD_DUMP_ONLY_HANGS) {547printf("ddebug: 'apitrace' can only appear once and not mixed with 'always'\n");548exit(1);549}550551if (!match_uint(&option, &apitrace_dump_call)) {552printf("ddebug: expected call number after 'apitrace'\n");553exit(1);554}555556mode = DD_DUMP_APITRACE_CALL;557} else if (match_uint(&option, &timeout)) {558/* no-op */559} else {560printf("ddebug: bad options: %s\n", option);561exit(1);562}563}564565dscreen = CALLOC_STRUCT(dd_screen);566if (!dscreen)567return NULL;568569#define SCR_INIT(_member) \570dscreen->base._member = screen->_member ? dd_screen_##_member : NULL571572dscreen->base.destroy = dd_screen_destroy;573dscreen->base.get_name = dd_screen_get_name;574dscreen->base.get_vendor = dd_screen_get_vendor;575dscreen->base.get_device_vendor = dd_screen_get_device_vendor;576SCR_INIT(get_disk_shader_cache);577dscreen->base.get_param = dd_screen_get_param;578dscreen->base.get_paramf = dd_screen_get_paramf;579dscreen->base.get_compute_param = dd_screen_get_compute_param;580dscreen->base.get_shader_param = dd_screen_get_shader_param;581dscreen->base.query_memory_info = dd_screen_query_memory_info;582/* get_video_param */583/* get_compute_param */584SCR_INIT(get_timestamp);585dscreen->base.context_create = dd_screen_context_create;586dscreen->base.is_format_supported = dd_screen_is_format_supported;587/* is_video_format_supported */588SCR_INIT(can_create_resource);589dscreen->base.resource_create = dd_screen_resource_create;590dscreen->base.resource_from_handle = dd_screen_resource_from_handle;591SCR_INIT(resource_from_memobj);592SCR_INIT(resource_from_user_memory);593SCR_INIT(check_resource_capability);594dscreen->base.resource_get_handle = dd_screen_resource_get_handle;595SCR_INIT(resource_get_param);596SCR_INIT(resource_get_info);597SCR_INIT(resource_changed);598dscreen->base.resource_destroy = dd_screen_resource_destroy;599SCR_INIT(flush_frontbuffer);600SCR_INIT(fence_reference);601SCR_INIT(fence_finish);602SCR_INIT(fence_get_fd);603SCR_INIT(memobj_create_from_handle);604SCR_INIT(memobj_destroy);605SCR_INIT(get_driver_query_info);606SCR_INIT(get_driver_query_group_info);607SCR_INIT(get_compiler_options);608SCR_INIT(get_driver_uuid);609SCR_INIT(get_device_uuid);610SCR_INIT(finalize_nir);611612#undef SCR_INIT613614dscreen->screen = screen;615dscreen->timeout_ms = timeout;616dscreen->dump_mode = mode;617dscreen->flush_always = flush;618dscreen->transfers = transfers;619dscreen->verbose = verbose;620dscreen->apitrace_dump_call = apitrace_dump_call;621622switch (dscreen->dump_mode) {623case DD_DUMP_ALL_CALLS:624fprintf(stderr, "Gallium debugger active. Logging all calls.\n");625break;626case DD_DUMP_APITRACE_CALL:627fprintf(stderr, "Gallium debugger active. Going to dump an apitrace call.\n");628break;629default:630fprintf(stderr, "Gallium debugger active.\n");631break;632}633634if (dscreen->timeout_ms > 0)635fprintf(stderr, "Hang detection timeout is %ums.\n", dscreen->timeout_ms);636else637fprintf(stderr, "Hang detection is disabled.\n");638639dscreen->skip_count = debug_get_num_option("GALLIUM_DDEBUG_SKIP", 0);640if (dscreen->skip_count > 0) {641fprintf(stderr, "Gallium debugger skipping the first %u draw calls.\n",642dscreen->skip_count);643}644645return &dscreen->base;646}647648649