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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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);
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
0
/**
 * 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);
   }
}
Ejemplo n.º 10
0
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;
}
Ejemplo n.º 11
0
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;
}
Ejemplo n.º 12
0
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;
}
Ejemplo n.º 13
0
/**
 * 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;
}
Ejemplo n.º 14
0
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;
}