boolean trace_dump_trace_begin() { const char *filename; filename = debug_get_option("GALLIUM_TRACE", NULL); if(!filename) return FALSE; if(!stream) { stream = fopen(filename, "wt"); if(!stream) return FALSE; trace_dump_writes("<?xml version='1.0' encoding='UTF-8'?>\n"); trace_dump_writes("<?xml-stylesheet type='text/xsl' href='trace.xsl'?>\n"); trace_dump_writes("<trace version='0.1'>\n"); #if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) /* Linux applications rarely cleanup GL / Gallium resources so catch * application exit here */ atexit(trace_dump_trace_close); #endif } ++refcount; return TRUE; }
static struct pipe_screen * swrast_screen_create (struct sw_winsys *ws) { const char *default_driver; const char *driver; struct pipe_screen *screen = NULL; #ifdef USE_LLVM default_driver = "llvmpipe"; #else default_driver = "softpipe"; #endif driver = debug_get_option ("GALLIUM_DRIVER", default_driver); #ifdef USE_LLVM if (screen == NULL && strcmp (driver, "llvmpipe") == 0) screen = llvmpipe_create_screen (ws); #endif if (screen == NULL) screen = softpipe_create_screen (ws); return screen; }
static void si_handle_env_var_force_family(struct si_screen *sscreen) { const char *family = debug_get_option("SI_FORCE_FAMILY", NULL); unsigned i; if (!family) return; for (i = CHIP_TAHITI; i < CHIP_LAST; i++) { if (!strcmp(family, r600_get_llvm_processor_name(i))) { /* Override family and chip_class. */ sscreen->b.family = sscreen->b.info.family = i; if (i >= CHIP_TONGA) sscreen->b.chip_class = sscreen->b.info.chip_class = VI; else if (i >= CHIP_BONAIRE) sscreen->b.chip_class = sscreen->b.info.chip_class = CIK; else sscreen->b.chip_class = sscreen->b.info.chip_class = SI; /* Don't submit any IBs. */ setenv("RADEON_NOOP", "1", 1); return; } } fprintf(stderr, "radeonsi: Unknown family: %s\n", family); exit(1); }
struct i915_winsys * i915_drm_winsys_create(int drmFD) { struct i915_drm_winsys *idws; unsigned int deviceID; idws = CALLOC_STRUCT(i915_drm_winsys); if (!idws) return NULL; i915_drm_get_device_id(drmFD, &deviceID); i915_drm_winsys_init_batchbuffer_functions(idws); i915_drm_winsys_init_buffer_functions(idws); i915_drm_winsys_init_fence_functions(idws); idws->fd = drmFD; idws->base.pci_id = deviceID; idws->max_batch_size = 16 * 4096; idws->base.destroy = i915_drm_winsys_destroy; idws->gem_manager = drm_intel_bufmgr_gem_init(idws->fd, idws->max_batch_size); drm_intel_bufmgr_gem_enable_reuse(idws->gem_manager); drm_intel_bufmgr_gem_enable_fenced_relocs(idws->gem_manager); idws->dump_cmd = debug_get_bool_option("I915_DUMP_CMD", FALSE); idws->dump_raw_file = debug_get_option("I915_DUMP_RAW_FILE", NULL); idws->send_cmd = !debug_get_bool_option("I915_NO_HW", FALSE); return &idws->base; }
static struct pipe_screen * gdi_screen_create(void) { const char *default_driver; const char *driver; struct pipe_screen *screen = NULL; struct sw_winsys *winsys; winsys = gdi_create_sw_winsys(); if(!winsys) goto no_winsys; #ifdef HAVE_LLVMPIPE default_driver = "llvmpipe"; #else default_driver = "softpipe"; #endif driver = debug_get_option("GALLIUM_DRIVER", default_driver); #ifdef HAVE_LLVMPIPE if (strcmp(driver, "llvmpipe") == 0) { screen = llvmpipe_create_screen( winsys ); } #else (void) driver; #endif if (screen == NULL) { screen = softpipe_create_screen( winsys ); } else { use_llvmpipe = TRUE; } if(!screen) goto no_screen; return screen; no_screen: winsys->destroy(winsys); no_winsys: return NULL; }
struct vl_screen *omx_get_screen(void) { static bool first_time = true; mtx_lock(&omx_lock); if (!omx_screen) { if (first_time) { omx_render_node = debug_get_option("OMX_RENDER_NODE", NULL); first_time = false; } if (omx_render_node) { drm_fd = loader_open_device(omx_render_node); if (drm_fd < 0) goto error; omx_screen = vl_drm_screen_create(drm_fd); if (!omx_screen) { close(drm_fd); goto error; } } else { omx_display = XOpenDisplay(NULL); if (!omx_display) goto error; omx_screen = vl_dri3_screen_create(omx_display, 0); if (!omx_screen) omx_screen = vl_dri2_screen_create(omx_display, 0); if (!omx_screen) { XCloseDisplay(omx_display); goto error; } } } ++omx_usecount; mtx_unlock(&omx_lock); return omx_screen; error: mtx_unlock(&omx_lock); return NULL; }
static struct pipe_screen * swrast_create_screen(struct sw_winsys *winsys) { const char *default_driver; const char *driver; struct pipe_screen *screen = NULL; #if defined(GALLIUM_CELL) default_driver = "cell"; #elif defined(GALLIUM_LLVMPIPE) default_driver = "llvmpipe"; #elif defined(GALLIUM_SOFTPIPE) default_driver = "softpipe"; #else default_driver = ""; #endif driver = debug_get_option("GALLIUM_DRIVER", default_driver); #if defined(GALLIUM_CELL) if (screen == NULL && strcmp(driver, "cell") == 0) screen = cell_create_screen( winsys ); #endif #if defined(GALLIUM_LLVMPIPE) if (screen == NULL && strcmp(driver, "llvmpipe") == 0) screen = llvmpipe_create_screen( winsys ); #endif #if defined(GALLIUM_SOFTPIPE) if (screen == NULL) screen = softpipe_create_screen( winsys ); #endif #if defined(GALLIUM_GALAHAD) if (screen) { struct pipe_screen *galahad_screen = galahad_screen_create(screen); if (galahad_screen) screen = galahad_screen; } #endif return screen; }
boolean trace_dump_trace_begin(void) { const char *filename; filename = debug_get_option("GALLIUM_TRACE", NULL); if (!filename) return FALSE; if (!stream) { if (strcmp(filename, "stderr") == 0) { close_stream = FALSE; stream = stderr; } else if (strcmp(filename, "stdout") == 0) { close_stream = FALSE; stream = stdout; } else { close_stream = TRUE; stream = fopen(filename, "wt"); if (!stream) return FALSE; } trace_dump_writes("<?xml version='1.0' encoding='UTF-8'?>\n"); trace_dump_writes("<?xml-stylesheet type='text/xsl' href='trace.xsl'?>\n"); trace_dump_writes("<trace version='0.1'>\n"); /* Many applications don't exit cleanly, others may create and destroy a * screen multiple times, so we only write </trace> tag and close at exit * time. */ atexit(trace_dump_trace_close); } return TRUE; }
/** * Log a reference count change to the log file (if enabled). * This is called via the pipe_reference() and debug_reference() functions, * basically whenever a reference count is initialized or changed. * * \param p the refcount being changed (the value is not changed here) * \param get_desc a function which will be called to print an object's * name/pointer into a string buffer during logging * \param change the reference count change which must be +/-1 or 0 when * creating the object and initializing the refcount. */ void debug_reference_slowpath(const struct pipe_reference *p, debug_reference_descriptor get_desc, int change) { assert(change >= -1); assert(change <= 1); if (debug_refcnt_state < 0) return; if (!debug_refcnt_state) { const char *filename = debug_get_option("GALLIUM_REFCNT_LOG", NULL); if (filename && filename[0]) stream = fopen(filename, "wt"); if (stream) debug_refcnt_state = 1; else debug_refcnt_state = -1; } if (debug_refcnt_state > 0) { struct debug_stack_frame frames[STACK_LEN]; const char *symbols[STACK_LEN]; char buf[1024]; unsigned i; unsigned refcnt = p->count; unsigned serial; boolean existing = debug_serial((void *) p, &serial); debug_backtrace_capture(frames, 1, STACK_LEN); for (i = 0; i < STACK_LEN; ++i) { if (frames[i].function) symbols[i] = debug_symbol_name_cached(frames[i].function); else symbols[i] = 0; } get_desc(buf, p); if (!existing) { fprintf(stream, "<%s> %p %u Create\n", buf, (void *) p, serial); dump_stack(symbols); /* this is here to provide a gradual change even if we don't see * the initialization */ for (i = 1; i <= refcnt - change; ++i) { fprintf(stream, "<%s> %p %u AddRef %u\n", buf, (void *) p, serial, i); dump_stack(symbols); } } if (change) { fprintf(stream, "<%s> %p %u %s %u\n", buf, (void *) p, serial, change > 0 ? "AddRef" : "Release", refcnt); dump_stack(symbols); } if (!refcnt) { debug_serial_delete((void *) p); fprintf(stream, "<%s> %p %u Destroy\n", buf, (void *) p, serial); dump_stack(symbols); } fflush(stream); } }
struct pipe_screen * ddebug_screen_create(struct pipe_screen *screen) { struct dd_screen *dscreen; const char *option; bool flush = false; bool verbose = false; bool transfers = false; unsigned timeout = 1000; unsigned apitrace_dump_call = 0; enum dd_dump_mode mode = DD_DUMP_ONLY_HANGS; option = debug_get_option("GALLIUM_DDEBUG", NULL); if (!option) return screen; if (!strcmp(option, "help")) { puts("Gallium driver debugger"); puts(""); puts("Usage:"); puts(""); puts(" GALLIUM_DDEBUG=\"[<timeout in ms>] [(always|apitrace <call#)] [flush] [transfers] [verbose]\""); puts(" GALLIUM_DDEBUG_SKIP=[count]"); puts(""); puts("Dump context and driver information of draw calls into"); puts("$HOME/"DD_DIR"/. By default, watch for GPU hangs and only dump information"); puts("about draw calls related to the hang."); puts(""); puts("<timeout in ms>"); puts(" Change the default timeout for GPU hang detection (default=1000ms)."); puts(" Setting this to 0 will disable GPU hang detection entirely."); puts(""); puts("always"); puts(" Dump information about all draw calls."); puts(""); puts("transfers"); puts(" Also dump and do hang detection on transfers."); puts(""); puts("apitrace <call#>"); puts(" Dump information about the draw call corresponding to the given"); puts(" apitrace call number and exit."); puts(""); puts("flush"); puts(" Flush after every draw call."); puts(""); puts("verbose"); puts(" Write additional information to stderr."); puts(""); puts("GALLIUM_DDEBUG_SKIP=count"); puts(" Skip dumping on the first count draw calls (only relevant with 'always')."); puts(""); exit(0); } for (;;) { skip_space(&option); if (!*option) break; if (match_word(&option, "always")) { if (mode == DD_DUMP_APITRACE_CALL) { printf("ddebug: both 'always' and 'apitrace' specified\n"); exit(1); } mode = DD_DUMP_ALL_CALLS; } else if (match_word(&option, "flush")) { flush = true; } else if (match_word(&option, "transfers")) { transfers = true; } else if (match_word(&option, "verbose")) { verbose = true; } else if (match_word(&option, "apitrace")) { if (mode != DD_DUMP_ONLY_HANGS) { printf("ddebug: 'apitrace' can only appear once and not mixed with 'always'\n"); exit(1); } if (!match_uint(&option, &apitrace_dump_call)) { printf("ddebug: expected call number after 'apitrace'\n"); exit(1); } mode = DD_DUMP_APITRACE_CALL; } else if (match_uint(&option, &timeout)) { /* no-op */ } else { printf("ddebug: bad options: %s\n", option); exit(1); } } dscreen = CALLOC_STRUCT(dd_screen); if (!dscreen) return NULL; #define SCR_INIT(_member) \ dscreen->base._member = screen->_member ? dd_screen_##_member : NULL dscreen->base.destroy = dd_screen_destroy; dscreen->base.get_name = dd_screen_get_name; dscreen->base.get_vendor = dd_screen_get_vendor; dscreen->base.get_device_vendor = dd_screen_get_device_vendor; SCR_INIT(get_disk_shader_cache); dscreen->base.get_param = dd_screen_get_param; dscreen->base.get_paramf = dd_screen_get_paramf; dscreen->base.get_compute_param = dd_screen_get_compute_param; dscreen->base.get_shader_param = dd_screen_get_shader_param; dscreen->base.query_memory_info = dd_screen_query_memory_info; /* get_video_param */ /* get_compute_param */ SCR_INIT(get_timestamp); dscreen->base.context_create = dd_screen_context_create; dscreen->base.is_format_supported = dd_screen_is_format_supported; /* is_video_format_supported */ SCR_INIT(can_create_resource); dscreen->base.resource_create = dd_screen_resource_create; dscreen->base.resource_from_handle = dd_screen_resource_from_handle; SCR_INIT(resource_from_memobj); SCR_INIT(resource_from_user_memory); SCR_INIT(check_resource_capability); dscreen->base.resource_get_handle = dd_screen_resource_get_handle; SCR_INIT(resource_changed); dscreen->base.resource_destroy = dd_screen_resource_destroy; SCR_INIT(flush_frontbuffer); SCR_INIT(fence_reference); SCR_INIT(fence_finish); SCR_INIT(memobj_create_from_handle); SCR_INIT(memobj_destroy); SCR_INIT(get_driver_query_info); SCR_INIT(get_driver_query_group_info); SCR_INIT(get_compiler_options); SCR_INIT(get_driver_uuid); SCR_INIT(get_device_uuid); #undef SCR_INIT dscreen->screen = screen; dscreen->timeout_ms = timeout; dscreen->dump_mode = mode; dscreen->flush_always = flush; dscreen->transfers = transfers; dscreen->verbose = verbose; dscreen->apitrace_dump_call = apitrace_dump_call; switch (dscreen->dump_mode) { case DD_DUMP_ALL_CALLS: fprintf(stderr, "Gallium debugger active. Logging all calls.\n"); break; case DD_DUMP_APITRACE_CALL: fprintf(stderr, "Gallium debugger active. Going to dump an apitrace call.\n"); break; default: fprintf(stderr, "Gallium debugger active.\n"); break; } if (dscreen->timeout_ms > 0) fprintf(stderr, "Hang detection timeout is %ums.\n", dscreen->timeout_ms); else fprintf(stderr, "Hang detection is disabled.\n"); dscreen->skip_count = debug_get_num_option("GALLIUM_DDEBUG_SKIP", 0); if (dscreen->skip_count > 0) { fprintf(stderr, "Gallium debugger skipping the first %u draw calls.\n", dscreen->skip_count); } return &dscreen->base; }
struct pipe_screen * ddebug_screen_create(struct pipe_screen *screen) { struct dd_screen *dscreen; const char *option = debug_get_option("GALLIUM_DDEBUG", NULL); bool dump_always = option && !strcmp(option, "always"); bool no_flush = option && strstr(option, "noflush"); bool help = option && !strcmp(option, "help"); unsigned timeout = 0; if (help) { puts("Gallium driver debugger"); puts(""); puts("Usage:"); puts(""); puts(" GALLIUM_DDEBUG=always"); puts(" Dump context and driver information after every draw call into"); puts(" $HOME/"DD_DIR"/."); puts(""); puts(" GALLIUM_DDEBUG=[timeout in ms] noflush"); puts(" Flush and detect a device hang after every draw call based on the given"); puts(" fence timeout and dump context and driver information into"); puts(" $HOME/"DD_DIR"/ when a hang is detected."); puts(" If 'noflush' is specified, only detect hangs in pipe->flush."); puts(""); puts(" GALLIUM_DDEBUG_SKIP=[count]"); puts(" Skip flush and hang detection for the given initial number of draw calls."); puts(""); exit(0); } if (!option) return screen; if (!dump_always && sscanf(option, "%u", &timeout) != 1) return screen; dscreen = CALLOC_STRUCT(dd_screen); if (!dscreen) return NULL; #define SCR_INIT(_member) \ dscreen->base._member = screen->_member ? dd_screen_##_member : NULL dscreen->base.destroy = dd_screen_destroy; dscreen->base.get_name = dd_screen_get_name; dscreen->base.get_vendor = dd_screen_get_vendor; dscreen->base.get_device_vendor = dd_screen_get_device_vendor; dscreen->base.get_param = dd_screen_get_param; dscreen->base.get_paramf = dd_screen_get_paramf; dscreen->base.get_shader_param = dd_screen_get_shader_param; /* get_video_param */ /* get_compute_param */ SCR_INIT(get_timestamp); dscreen->base.context_create = dd_screen_context_create; dscreen->base.is_format_supported = dd_screen_is_format_supported; /* is_video_format_supported */ SCR_INIT(can_create_resource); dscreen->base.resource_create = dd_screen_resource_create; dscreen->base.resource_from_handle = dd_screen_resource_from_handle; SCR_INIT(resource_from_user_memory); dscreen->base.resource_get_handle = dd_screen_resource_get_handle; dscreen->base.resource_destroy = dd_screen_resource_destroy; SCR_INIT(flush_frontbuffer); SCR_INIT(fence_reference); SCR_INIT(fence_finish); SCR_INIT(get_driver_query_info); SCR_INIT(get_driver_query_group_info); #undef SCR_INIT dscreen->screen = screen; dscreen->timeout_ms = timeout; dscreen->mode = dump_always ? DD_DUMP_ALL_CALLS : DD_DETECT_HANGS; dscreen->no_flush = no_flush; switch (dscreen->mode) { case DD_DUMP_ALL_CALLS: fprintf(stderr, "Gallium debugger active. Logging all calls.\n"); break; case DD_DETECT_HANGS: fprintf(stderr, "Gallium debugger active. " "The hang detection timout is %i ms.\n", timeout); break; default: assert(0); } dscreen->skip_count = debug_get_num_option("GALLIUM_DDEBUG_SKIP", 0); if (dscreen->skip_count > 0) { fprintf(stderr, "Gallium debugger skipping the first %u draw calls.\n", dscreen->skip_count); } return &dscreen->base; }
struct pipe_screen * nvfx_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) { static const unsigned query_sizes[] = {(4096 - 4 * 32) / 32, 3 * 1024 / 32, 2 * 1024 / 32, 1024 / 32}; struct nvfx_screen *screen = CALLOC_STRUCT(nvfx_screen); struct nouveau_channel *chan; struct pipe_screen *pscreen; unsigned eng3d_class = 0; int ret, i; if (!screen) return NULL; pscreen = &screen->base.base; ret = nouveau_screen_init(&screen->base, dev); if (ret) { nvfx_screen_destroy(pscreen); return NULL; } chan = screen->base.channel; screen->cur_ctx = NULL; chan->user_private = screen; chan->flush_notify = nvfx_channel_flush_notify; pscreen->winsys = ws; pscreen->destroy = nvfx_screen_destroy; pscreen->get_param = nvfx_screen_get_param; pscreen->get_shader_param = nvfx_screen_get_shader_param; pscreen->get_paramf = nvfx_screen_get_paramf; pscreen->is_format_supported = nvfx_screen_is_format_supported; pscreen->context_create = nvfx_create; switch (dev->chipset & 0xf0) { case 0x30: if (NV30_3D_CHIPSET_3X_MASK & (1 << (dev->chipset & 0x0f))) eng3d_class = NV30_3D; else if (NV34_3D_CHIPSET_3X_MASK & (1 << (dev->chipset & 0x0f))) eng3d_class = NV34_3D; else if (NV35_3D_CHIPSET_3X_MASK & (1 << (dev->chipset & 0x0f))) eng3d_class = NV35_3D; break; case 0x40: if (NV4X_GRCLASS4097_CHIPSETS & (1 << (dev->chipset & 0x0f))) eng3d_class = NV40_3D; else if (NV4X_GRCLASS4497_CHIPSETS & (1 << (dev->chipset & 0x0f))) eng3d_class = NV44_3D; screen->is_nv4x = ~0; break; case 0x60: if (NV6X_GRCLASS4497_CHIPSETS & (1 << (dev->chipset & 0x0f))) eng3d_class = NV44_3D; screen->is_nv4x = ~0; break; } if (!eng3d_class) { NOUVEAU_ERR("Unknown nv3x/nv4x chipset: nv%02x\n", dev->chipset); return NULL; } screen->advertise_npot = !!screen->is_nv4x; screen->advertise_blend_equation_separate = !!screen->is_nv4x; screen->use_nv4x = screen->is_nv4x; if(screen->is_nv4x) { if(debug_get_bool_option("NVFX_SIMULATE_NV30", FALSE)) screen->use_nv4x = 0; if(!debug_get_bool_option("NVFX_NPOT", TRUE)) screen->advertise_npot = 0; if(!debug_get_bool_option("NVFX_BLEND_EQ_SEP", TRUE)) screen->advertise_blend_equation_separate = 0; } screen->force_swtnl = debug_get_bool_option("NVFX_SWTNL", FALSE); screen->trace_draw = debug_get_bool_option("NVFX_TRACE_DRAW", FALSE); screen->buffer_allocation_cost = debug_get_num_option("NVFX_BUFFER_ALLOCATION_COST", 16384); screen->inline_cost_per_hardware_cost = atof(debug_get_option("NVFX_INLINE_COST_PER_HARDWARE_COST", "1.0")); screen->static_reuse_threshold = atof(debug_get_option("NVFX_STATIC_REUSE_THRESHOLD", "2.0")); /* We don't advertise these by default because filtering and blending doesn't work as * it should, due to several restrictions. * The only exception is fp16 on nv40. */ screen->advertise_fp16 = debug_get_bool_option("NVFX_FP16", !!screen->use_nv4x); screen->advertise_fp32 = debug_get_bool_option("NVFX_FP32", 0); screen->vertex_buffer_reloc_flags = nvfx_screen_get_vertex_buffer_flags(screen); /* surely both nv3x and nv44 support index buffers too: find out how and test that */ if(eng3d_class == NV40_3D) screen->index_buffer_reloc_flags = screen->vertex_buffer_reloc_flags; if(!screen->force_swtnl && screen->vertex_buffer_reloc_flags == screen->index_buffer_reloc_flags) screen->base.vertex_buffer_flags = screen->base.index_buffer_flags = screen->vertex_buffer_reloc_flags; nvfx_screen_init_resource_functions(pscreen); ret = nouveau_grobj_alloc(chan, 0xbeef3097, eng3d_class, &screen->eng3d); if (ret) { NOUVEAU_ERR("Error creating 3D object: %d\n", ret); return FALSE; } /* 2D engine setup */ nvfx_screen_surface_init(pscreen); /* Notifier for sync purposes */ ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync); if (ret) { NOUVEAU_ERR("Error creating notifier object: %d\n", ret); nvfx_screen_destroy(pscreen); return NULL; } /* Query objects */ for(i = 0; i < sizeof(query_sizes) / sizeof(query_sizes[0]); ++i) { ret = nouveau_notifier_alloc(chan, 0xbeef0302, query_sizes[i], &screen->query); if(!ret) break; } if (ret) { NOUVEAU_ERR("Error initialising query objects: %d\n", ret); nvfx_screen_destroy(pscreen); return NULL; } ret = nouveau_resource_init(&screen->query_heap, 0, query_sizes[i]); if (ret) { NOUVEAU_ERR("Error initialising query object heap: %d\n", ret); nvfx_screen_destroy(pscreen); return NULL; } LIST_INITHEAD(&screen->query_list); /* Vtxprog resources */ if (nouveau_resource_init(&screen->vp_exec_heap, 0, screen->use_nv4x ? 512 : 256) || nouveau_resource_init(&screen->vp_data_heap, 0, screen->use_nv4x ? 468 : 256)) { nvfx_screen_destroy(pscreen); return NULL; } BIND_RING(chan, screen->eng3d, 7); /* Static eng3d initialisation */ /* note that we just started using the channel, so we must have space in the pushbuffer */ OUT_RING(chan, RING_3D(NV30_3D_DMA_NOTIFY, 1)); OUT_RING(chan, screen->sync->handle); OUT_RING(chan, RING_3D(NV30_3D_DMA_TEXTURE0, 2)); OUT_RING(chan, chan->vram->handle); OUT_RING(chan, chan->gart->handle); OUT_RING(chan, RING_3D(NV30_3D_DMA_COLOR1, 1)); OUT_RING(chan, chan->vram->handle); OUT_RING(chan, RING_3D(NV30_3D_DMA_COLOR0, 2)); OUT_RING(chan, chan->vram->handle); OUT_RING(chan, chan->vram->handle); OUT_RING(chan, RING_3D(NV30_3D_DMA_VTXBUF0, 2)); OUT_RING(chan, chan->vram->handle); OUT_RING(chan, chan->gart->handle); OUT_RING(chan, RING_3D(NV30_3D_DMA_FENCE, 2)); OUT_RING(chan, 0); OUT_RING(chan, screen->query->handle); OUT_RING(chan, RING_3D(NV30_3D_DMA_UNK1AC, 2)); OUT_RING(chan, chan->vram->handle); OUT_RING(chan, chan->vram->handle); if(!screen->is_nv4x) nv30_screen_init(screen); else nv40_screen_init(screen); return pscreen; }
/** * Create a new brw_screen object */ struct pipe_screen * brw_screen_create(struct brw_winsys_screen *sws) { struct brw_screen *bscreen; struct brw_chipset chipset; #ifdef DEBUG BRW_DEBUG = debug_get_flags_option("BRW_DEBUG", debug_names, 0); BRW_DEBUG |= debug_get_flags_option("INTEL_DEBUG", debug_names, 0); BRW_DEBUG |= DEBUG_STATS | DEBUG_MIN_URB | DEBUG_WM; BRW_DUMP = debug_get_flags_option("BRW_DUMP", dump_names, 0); #endif memset(&chipset, 0, sizeof chipset); chipset.pci_id = sws->pci_id; switch (chipset.pci_id) { case PCI_CHIP_I965_G: case PCI_CHIP_I965_Q: case PCI_CHIP_I965_G_1: case PCI_CHIP_I946_GZ: case PCI_CHIP_I965_GM: case PCI_CHIP_I965_GME: chipset.is_965 = TRUE; break; case PCI_CHIP_GM45_GM: case PCI_CHIP_IGD_E_G: case PCI_CHIP_Q45_G: case PCI_CHIP_G45_G: case PCI_CHIP_G41_G: case PCI_CHIP_B43_G: chipset.is_g4x = TRUE; break; case PCI_CHIP_ILD_G: case PCI_CHIP_ILM_G: chipset.is_igdng = TRUE; break; default: debug_printf("%s: unknown pci id 0x%x, cannot create screen\n", __FUNCTION__, chipset.pci_id); return NULL; } bscreen = CALLOC_STRUCT(brw_screen); if (!bscreen) return NULL; bscreen->chipset = chipset; bscreen->sws = sws; bscreen->base.winsys = NULL; bscreen->base.destroy = brw_destroy_screen; bscreen->base.get_name = brw_get_name; bscreen->base.get_vendor = brw_get_vendor; bscreen->base.get_param = brw_get_param; bscreen->base.get_shader_param = brw_get_shader_param; bscreen->base.get_paramf = brw_get_paramf; bscreen->base.is_format_supported = brw_is_format_supported; bscreen->base.context_create = brw_create_context; bscreen->base.fence_reference = brw_fence_reference; bscreen->base.fence_signalled = brw_fence_signalled; bscreen->base.fence_finish = brw_fence_finish; brw_init_screen_resource_functions(bscreen); brw_screen_tex_surface_init(bscreen); bscreen->no_tiling = debug_get_option("BRW_NO_TILING", FALSE) != NULL; return &bscreen->base; }
struct pipe_screen *radeonsi_screen_create(struct radeon_winsys *ws, const struct pipe_screen_config *config) { struct si_screen *sscreen = CALLOC_STRUCT(si_screen); unsigned hw_threads, num_comp_hi_threads, num_comp_lo_threads, i; if (!sscreen) { return NULL; } sscreen->ws = ws; ws->query_info(ws, &sscreen->info); if (sscreen->info.chip_class >= GFX9) { sscreen->se_tile_repeat = 32 * sscreen->info.max_se; } else { ac_get_raster_config(&sscreen->info, &sscreen->pa_sc_raster_config, &sscreen->pa_sc_raster_config_1, &sscreen->se_tile_repeat); } sscreen->debug_flags = debug_get_flags_option("R600_DEBUG", debug_options, 0); sscreen->debug_flags |= debug_get_flags_option("AMD_DEBUG", debug_options, 0); /* Set functions first. */ sscreen->b.context_create = si_pipe_create_context; sscreen->b.destroy = si_destroy_screen; sscreen->b.set_max_shader_compiler_threads = si_set_max_shader_compiler_threads; sscreen->b.is_parallel_shader_compilation_finished = si_is_parallel_shader_compilation_finished; si_init_screen_get_functions(sscreen); si_init_screen_buffer_functions(sscreen); si_init_screen_fence_functions(sscreen); si_init_screen_state_functions(sscreen); si_init_screen_texture_functions(sscreen); si_init_screen_query_functions(sscreen); /* Set these flags in debug_flags early, so that the shader cache takes * them into account. */ if (driQueryOptionb(config->options, "glsl_correct_derivatives_after_discard")) sscreen->debug_flags |= DBG(FS_CORRECT_DERIVS_AFTER_KILL); if (driQueryOptionb(config->options, "radeonsi_enable_sisched")) sscreen->debug_flags |= DBG(SI_SCHED); if (sscreen->debug_flags & DBG(INFO)) ac_print_gpu_info(&sscreen->info); slab_create_parent(&sscreen->pool_transfers, sizeof(struct si_transfer), 64); sscreen->force_aniso = MIN2(16, debug_get_num_option("R600_TEX_ANISO", -1)); if (sscreen->force_aniso >= 0) { printf("radeonsi: Forcing anisotropy filter to %ix\n", /* round down to a power of two */ 1 << util_logbase2(sscreen->force_aniso)); } (void) mtx_init(&sscreen->aux_context_lock, mtx_plain); (void) mtx_init(&sscreen->gpu_load_mutex, mtx_plain); si_init_gs_info(sscreen); if (!si_init_shader_cache(sscreen)) { FREE(sscreen); return NULL; } si_disk_cache_create(sscreen); /* Determine the number of shader compiler threads. */ hw_threads = sysconf(_SC_NPROCESSORS_ONLN); if (hw_threads >= 12) { num_comp_hi_threads = hw_threads * 3 / 4; num_comp_lo_threads = hw_threads / 3; } else if (hw_threads >= 6) { num_comp_hi_threads = hw_threads - 2; num_comp_lo_threads = hw_threads / 2; } else if (hw_threads >= 2) { num_comp_hi_threads = hw_threads - 1; num_comp_lo_threads = hw_threads / 2; } else { num_comp_hi_threads = 1; num_comp_lo_threads = 1; } num_comp_hi_threads = MIN2(num_comp_hi_threads, ARRAY_SIZE(sscreen->compiler)); num_comp_lo_threads = MIN2(num_comp_lo_threads, ARRAY_SIZE(sscreen->compiler_lowp)); if (!util_queue_init(&sscreen->shader_compiler_queue, "sh", 64, num_comp_hi_threads, UTIL_QUEUE_INIT_RESIZE_IF_FULL | UTIL_QUEUE_INIT_SET_FULL_THREAD_AFFINITY)) { si_destroy_shader_cache(sscreen); FREE(sscreen); return NULL; } if (!util_queue_init(&sscreen->shader_compiler_queue_low_priority, "shlo", 64, num_comp_lo_threads, UTIL_QUEUE_INIT_RESIZE_IF_FULL | UTIL_QUEUE_INIT_SET_FULL_THREAD_AFFINITY | UTIL_QUEUE_INIT_USE_MINIMUM_PRIORITY)) { si_destroy_shader_cache(sscreen); FREE(sscreen); return NULL; } if (!debug_get_bool_option("RADEON_DISABLE_PERFCOUNTERS", false)) si_init_perfcounters(sscreen); /* Determine tessellation ring info. */ bool double_offchip_buffers = sscreen->info.chip_class >= CIK && sscreen->info.family != CHIP_CARRIZO && sscreen->info.family != CHIP_STONEY; /* This must be one less than the maximum number due to a hw limitation. * Various hardware bugs in SI, CIK, and GFX9 need this. */ unsigned max_offchip_buffers_per_se; /* Only certain chips can use the maximum value. */ if (sscreen->info.family == CHIP_VEGA12 || sscreen->info.family == CHIP_VEGA20) max_offchip_buffers_per_se = double_offchip_buffers ? 128 : 64; else max_offchip_buffers_per_se = double_offchip_buffers ? 127 : 63; unsigned max_offchip_buffers = max_offchip_buffers_per_se * sscreen->info.max_se; unsigned offchip_granularity; /* Hawaii has a bug with offchip buffers > 256 that can be worked * around by setting 4K granularity. */ if (sscreen->info.family == CHIP_HAWAII) { sscreen->tess_offchip_block_dw_size = 4096; offchip_granularity = V_03093C_X_4K_DWORDS; } else { sscreen->tess_offchip_block_dw_size = 8192; offchip_granularity = V_03093C_X_8K_DWORDS; } sscreen->tess_factor_ring_size = 32768 * sscreen->info.max_se; assert(((sscreen->tess_factor_ring_size / 4) & C_030938_SIZE) == 0); sscreen->tess_offchip_ring_size = max_offchip_buffers * sscreen->tess_offchip_block_dw_size * 4; if (sscreen->info.chip_class >= CIK) { if (sscreen->info.chip_class >= VI) --max_offchip_buffers; sscreen->vgt_hs_offchip_param = S_03093C_OFFCHIP_BUFFERING(max_offchip_buffers) | S_03093C_OFFCHIP_GRANULARITY(offchip_granularity); } else { assert(offchip_granularity == V_03093C_X_8K_DWORDS); sscreen->vgt_hs_offchip_param = S_0089B0_OFFCHIP_BUFFERING(max_offchip_buffers); } /* The mere presense of CLEAR_STATE in the IB causes random GPU hangs * on SI. Some CLEAR_STATE cause asic hang on radeon kernel, etc. * SPI_VS_OUT_CONFIG. So only enable CI CLEAR_STATE on amdgpu kernel.*/ sscreen->has_clear_state = sscreen->info.chip_class >= CIK && sscreen->info.drm_major == 3; sscreen->has_distributed_tess = sscreen->info.chip_class >= VI && sscreen->info.max_se >= 2; sscreen->has_draw_indirect_multi = (sscreen->info.family >= CHIP_POLARIS10) || (sscreen->info.chip_class == VI && sscreen->info.pfp_fw_version >= 121 && sscreen->info.me_fw_version >= 87) || (sscreen->info.chip_class == CIK && sscreen->info.pfp_fw_version >= 211 && sscreen->info.me_fw_version >= 173) || (sscreen->info.chip_class == SI && sscreen->info.pfp_fw_version >= 79 && sscreen->info.me_fw_version >= 142); sscreen->has_out_of_order_rast = sscreen->info.chip_class >= VI && sscreen->info.max_se >= 2 && !(sscreen->debug_flags & DBG(NO_OUT_OF_ORDER)); sscreen->assume_no_z_fights = driQueryOptionb(config->options, "radeonsi_assume_no_z_fights"); sscreen->commutative_blend_add = driQueryOptionb(config->options, "radeonsi_commutative_blend_add"); { #define OPT_BOOL(name, dflt, description) \ sscreen->options.name = \ driQueryOptionb(config->options, "radeonsi_"#name); #include "si_debug_options.h" } sscreen->has_gfx9_scissor_bug = sscreen->info.family == CHIP_VEGA10 || sscreen->info.family == CHIP_RAVEN; sscreen->has_msaa_sample_loc_bug = (sscreen->info.family >= CHIP_POLARIS10 && sscreen->info.family <= CHIP_POLARIS12) || sscreen->info.family == CHIP_VEGA10 || sscreen->info.family == CHIP_RAVEN; sscreen->has_ls_vgpr_init_bug = sscreen->info.family == CHIP_VEGA10 || sscreen->info.family == CHIP_RAVEN; sscreen->has_dcc_constant_encode = sscreen->info.family == CHIP_RAVEN2; /* Only enable primitive binning on APUs by default. */ sscreen->dpbb_allowed = sscreen->info.family == CHIP_RAVEN || sscreen->info.family == CHIP_RAVEN2; sscreen->dfsm_allowed = sscreen->info.family == CHIP_RAVEN || sscreen->info.family == CHIP_RAVEN2; /* Process DPBB enable flags. */ if (sscreen->debug_flags & DBG(DPBB)) { sscreen->dpbb_allowed = true; if (sscreen->debug_flags & DBG(DFSM)) sscreen->dfsm_allowed = true; } /* Process DPBB disable flags. */ if (sscreen->debug_flags & DBG(NO_DPBB)) { sscreen->dpbb_allowed = false; sscreen->dfsm_allowed = false; } else if (sscreen->debug_flags & DBG(NO_DFSM)) { sscreen->dfsm_allowed = false; } /* While it would be nice not to have this flag, we are constrained * by the reality that LLVM 5.0 doesn't have working VGPR indexing * on GFX9. */ sscreen->llvm_has_working_vgpr_indexing = sscreen->info.chip_class <= VI; /* Some chips have RB+ registers, but don't support RB+. Those must * always disable it. */ if (sscreen->info.family == CHIP_STONEY || sscreen->info.chip_class >= GFX9) { sscreen->has_rbplus = true; sscreen->rbplus_allowed = !(sscreen->debug_flags & DBG(NO_RB_PLUS)) && (sscreen->info.family == CHIP_STONEY || sscreen->info.family == CHIP_VEGA12 || sscreen->info.family == CHIP_RAVEN || sscreen->info.family == CHIP_RAVEN2); } sscreen->dcc_msaa_allowed = !(sscreen->debug_flags & DBG(NO_DCC_MSAA)); sscreen->cpdma_prefetch_writes_memory = sscreen->info.chip_class <= VI; (void) mtx_init(&sscreen->shader_parts_mutex, mtx_plain); sscreen->use_monolithic_shaders = (sscreen->debug_flags & DBG(MONOLITHIC_SHADERS)) != 0; sscreen->barrier_flags.cp_to_L2 = SI_CONTEXT_INV_SMEM_L1 | SI_CONTEXT_INV_VMEM_L1; if (sscreen->info.chip_class <= VI) { sscreen->barrier_flags.cp_to_L2 |= SI_CONTEXT_INV_GLOBAL_L2; sscreen->barrier_flags.L2_to_cp |= SI_CONTEXT_WRITEBACK_GLOBAL_L2; } if (debug_get_bool_option("RADEON_DUMP_SHADERS", false)) sscreen->debug_flags |= DBG_ALL_SHADERS; /* Syntax: * EQAA=s,z,c * Example: * EQAA=8,4,2 * That means 8 coverage samples, 4 Z/S samples, and 2 color samples. * Constraints: * s >= z >= c (ignoring this only wastes memory) * s = [2..16] * z = [2..8] * c = [2..8] * * Only MSAA color and depth buffers are overriden. */ if (sscreen->info.has_eqaa_surface_allocator) { const char *eqaa = debug_get_option("EQAA", NULL); unsigned s,z,f; if (eqaa && sscanf(eqaa, "%u,%u,%u", &s, &z, &f) == 3 && s && z && f) { sscreen->eqaa_force_coverage_samples = s; sscreen->eqaa_force_z_samples = z; sscreen->eqaa_force_color_samples = f; } } for (i = 0; i < num_comp_hi_threads; i++) si_init_compiler(sscreen, &sscreen->compiler[i]); for (i = 0; i < num_comp_lo_threads; i++) si_init_compiler(sscreen, &sscreen->compiler_lowp[i]); /* Create the auxiliary context. This must be done last. */ sscreen->aux_context = si_create_context( &sscreen->b, sscreen->options.aux_debug ? PIPE_CONTEXT_DEBUG : 0); if (sscreen->options.aux_debug) { struct u_log_context *log = CALLOC_STRUCT(u_log_context); u_log_context_init(log); sscreen->aux_context->set_log_context(sscreen->aux_context, log); } if (sscreen->debug_flags & DBG(TEST_DMA)) si_test_dma(sscreen); if (sscreen->debug_flags & DBG(TEST_DMA_PERF)) { si_test_dma_perf(sscreen); } if (sscreen->debug_flags & (DBG(TEST_VMFAULT_CP) | DBG(TEST_VMFAULT_SDMA) | DBG(TEST_VMFAULT_SHADER))) si_test_vmfault(sscreen); if (sscreen->debug_flags & DBG(TEST_GDS)) si_test_gds((struct si_context*)sscreen->aux_context); if (sscreen->debug_flags & DBG(TEST_GDS_MM)) { si_test_gds_memory_management((struct si_context*)sscreen->aux_context, 32 * 1024, 4, RADEON_DOMAIN_GDS); } if (sscreen->debug_flags & DBG(TEST_GDS_OA_MM)) { si_test_gds_memory_management((struct si_context*)sscreen->aux_context, 4, 1, RADEON_DOMAIN_OA); } return &sscreen->b; }