Ejemplo n.º 1
0
int
nvc0_screen_get_driver_query_info(struct pipe_screen *pscreen,
                                  unsigned id,
                                  struct pipe_driver_query_info *info)
{
   struct nvc0_screen *screen = nvc0_screen(pscreen);
   int num_sw_queries = 0, num_hw_queries = 0;

   num_sw_queries = nvc0_sw_get_driver_query_info(screen, 0, NULL);
   num_hw_queries = nvc0_hw_get_driver_query_info(screen, 0, NULL);

   if (!info)
      return num_sw_queries + num_hw_queries;

   /* Init default values. */
   info->name = "this_is_not_the_query_you_are_looking_for";
   info->query_type = 0xdeadd01d;
   info->max_value.u64 = 0;
   info->type = PIPE_DRIVER_QUERY_TYPE_UINT64;
   info->group_id = -1;
   info->flags = 0;

#ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
   if (id < num_sw_queries)
      return nvc0_sw_get_driver_query_info(screen, id, info);
#endif

   return nvc0_hw_get_driver_query_info(screen, id - num_sw_queries, info);
}
Ejemplo n.º 2
0
struct pipe_context *
nvc0_create(struct pipe_screen *pscreen, void *priv)
{
   struct nvc0_screen *screen = nvc0_screen(pscreen);
   struct nvc0_context *nvc0;
   struct pipe_context *pipe;

   nvc0 = CALLOC_STRUCT(nvc0_context);
   if (!nvc0)
      return NULL;
   pipe = &nvc0->base.pipe;

   nvc0->screen = screen;
   nvc0->base.screen    = &screen->base;
   nvc0->base.copy_data = nvc0_m2mf_copy_linear;
   nvc0->base.push_data = nvc0_m2mf_push_linear;
   nvc0->base.push_cb = nvc0_cb_push;

   pipe->screen = pscreen;
   pipe->priv = priv;

   pipe->destroy = nvc0_destroy;

   pipe->draw_vbo = nvc0_draw_vbo;
   pipe->clear = nvc0_clear;

   pipe->flush = nvc0_flush;
   pipe->texture_barrier = nvc0_texture_barrier;

   if (!screen->cur_ctx)
      screen->cur_ctx = nvc0;
   screen->base.channel->flush_notify = nvc0_default_flush_notify;

   nvc0_init_query_functions(nvc0);
   nvc0_init_surface_functions(nvc0);
   nvc0_init_state_functions(nvc0);
   nvc0_init_resource_functions(pipe);

   nvc0->draw = draw_create(pipe);
   assert(nvc0->draw);
   draw_set_rasterize_stage(nvc0->draw, nvc0_draw_render_stage(nvc0));

   pipe->create_video_decoder = nvc0_create_decoder;
   pipe->create_video_buffer = nvc0_video_buffer_create;

   /* shader builtin library is per-screen, but we need a context for m2mf */
   nvc0_program_library_upload(nvc0);

   return pipe;
}
Ejemplo n.º 3
0
struct pipe_context *
nvc0_create(struct pipe_screen *pscreen, void *priv)
{
   struct pipe_winsys *pipe_winsys = pscreen->winsys;
   struct nvc0_screen *screen = nvc0_screen(pscreen);
   struct nvc0_context *nvc0;
   struct pipe_context *pipe;

   nvc0 = CALLOC_STRUCT(nvc0_context);
   if (!nvc0)
      return NULL;
   pipe = &nvc0->base.pipe;

   nvc0->screen = screen;
   nvc0->base.screen    = &screen->base;
   nvc0->base.copy_data = nvc0_m2mf_copy_linear;
   nvc0->base.push_data = nvc0_m2mf_push_linear;

   pipe->winsys = pipe_winsys;
   pipe->screen = pscreen;
   pipe->priv = priv;

   pipe->destroy = nvc0_destroy;

   pipe->draw_vbo = nvc0_draw_vbo;
   pipe->clear = nvc0_clear;

   pipe->flush = nvc0_flush;
   pipe->texture_barrier = nvc0_texture_barrier;

   if (!screen->cur_ctx)
      screen->cur_ctx = nvc0;
   screen->base.channel->flush_notify = nvc0_default_flush_notify;

   nvc0_init_query_functions(nvc0);
   nvc0_init_surface_functions(nvc0);
   nvc0_init_state_functions(nvc0);
   nvc0_init_resource_functions(pipe);

   nvc0->draw = draw_create(pipe);
   assert(nvc0->draw);
   draw_set_rasterize_stage(nvc0->draw, nvc0_draw_render_stage(nvc0));

   nouveau_context_init_vdec(&nvc0->base);

   return pipe;
}
Ejemplo n.º 4
0
static int
nvc0_screen_get_compute_param(struct pipe_screen *pscreen,
                              enum pipe_compute_cap param, void *data)
{
   struct nvc0_screen *screen = nvc0_screen(pscreen);
   const uint16_t obj_class = screen->compute->oclass;

#define RET(x) do {                  \
   if (data)                         \
      memcpy(data, x, sizeof(x));    \
   return sizeof(x);                 \
} while (0)

   switch (param) {
   case PIPE_COMPUTE_CAP_GRID_DIMENSION:
      RET((uint64_t []) { 3 });
   case PIPE_COMPUTE_CAP_MAX_GRID_SIZE:
      if (obj_class >= NVE4_COMPUTE_CLASS) {
         RET(((uint64_t []) { 0x7fffffff, 65535, 65535 }));
      } else {
Ejemplo n.º 5
0
int
nvc0_screen_get_driver_query_info(struct pipe_screen *pscreen,
                                  unsigned id,
                                  struct pipe_driver_query_info *info)
{
   struct nvc0_screen *screen = nvc0_screen(pscreen);
   int count = 0;

   count += NVC0_QUERY_DRV_STAT_COUNT;

   if (screen->base.class_3d >= NVE4_3D_CLASS) {
      if (screen->base.device->drm_version >= 0x01000101)
         count += NVE4_PM_QUERY_COUNT;
   }
   if (!info)
      return count;

#ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
   if (id < NVC0_QUERY_DRV_STAT_COUNT) {
      info->name = nvc0_drv_stat_names[id];
      info->query_type = NVC0_QUERY_DRV_STAT(id);
      info->max_value = ~0ULL;
      info->uses_byte_units = !!strstr(info->name, "bytes");
      return 1;
   } else
#endif
   if (id < count) {
      info->name = nve4_pm_query_names[id - NVC0_QUERY_DRV_STAT_COUNT];
      info->query_type = NVE4_PM_QUERY(id - NVC0_QUERY_DRV_STAT_COUNT);
      info->max_value = (id < NVE4_PM_QUERY_METRIC_MP_OCCUPANCY) ?
         ~0ULL : 100;
      info->uses_byte_units = FALSE;
      return 1;
   }
   /* user asked for info about non-existing query */
   info->name = "this_is_not_the_query_you_are_looking_for";
   info->query_type = 0xdeadd01d;
   info->max_value = 0;
   info->uses_byte_units = FALSE;
   return 0;
}
Ejemplo n.º 6
0
int
nvc0_screen_get_driver_query_group_info(struct pipe_screen *pscreen,
                                        unsigned id,
                                        struct pipe_driver_query_group_info *info)
{
   struct nvc0_screen *screen = nvc0_screen(pscreen);
   int count = 0;

#ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
   count++;
#endif

   if (screen->base.drm->version >= 0x01000101) {
      if (screen->compute) {
         if (screen->base.class_3d <= GM200_3D_CLASS) {
            count += 2;
         }
      }
   }

   if (!info)
      return count;

   if (id == NVC0_HW_SM_QUERY_GROUP) {
      if (screen->compute) {
         info->name = "MP counters";

         /* Expose the maximum number of hardware counters available, although
          * some queries use more than one counter. Expect failures in that
          * case but as performance counters are for developers, this should
          * not have a real impact. */
         info->max_active_queries = 8;
         info->num_queries = nvc0_hw_sm_get_num_queries(screen);
         return 1;
      }
   } else
   if (id == NVC0_HW_METRIC_QUERY_GROUP) {
      if (screen->compute) {
          if (screen->base.class_3d <= GM200_3D_CLASS) {
            info->name = "Performance metrics";
            info->max_active_queries = 4; /* A metric uses at least 2 queries */
            info->num_queries = nvc0_hw_metric_get_num_queries(screen);
            return 1;
         }
      }
   }
#ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
   else if (id == NVC0_SW_QUERY_DRV_STAT_GROUP) {
      info->name = "Driver statistics";
      info->max_active_queries = NVC0_SW_QUERY_DRV_STAT_COUNT;
      info->num_queries = NVC0_SW_QUERY_DRV_STAT_COUNT;
      return 1;
   }
#endif

   /* user asked for info about non-existing query group */
   info->name = "this_is_not_the_query_group_you_are_looking_for";
   info->max_active_queries = 0;
   info->num_queries = 0;
   return 0;
}
Ejemplo n.º 7
0
struct pipe_context *
nvc0_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags)
{
    struct nvc0_screen *screen = nvc0_screen(pscreen);
    struct nvc0_context *nvc0;
    struct pipe_context *pipe;
    int ret;
    uint32_t flags;

    nvc0 = CALLOC_STRUCT(nvc0_context);
    if (!nvc0)
        return NULL;
    pipe = &nvc0->base.pipe;

    if (!nvc0_blitctx_create(nvc0))
        goto out_err;

    nvc0->base.pushbuf = screen->base.pushbuf;
    nvc0->base.client = screen->base.client;

    ret = nouveau_bufctx_new(screen->base.client, 2, &nvc0->bufctx);
    if (!ret)
        ret = nouveau_bufctx_new(screen->base.client, NVC0_BIND_3D_COUNT,
                                 &nvc0->bufctx_3d);
    if (!ret)
        ret = nouveau_bufctx_new(screen->base.client, NVC0_BIND_CP_COUNT,
                                 &nvc0->bufctx_cp);
    if (ret)
        goto out_err;

    nvc0->screen = screen;
    nvc0->base.screen = &screen->base;

    pipe->screen = pscreen;
    pipe->priv = priv;

    pipe->destroy = nvc0_destroy;

    pipe->draw_vbo = nvc0_draw_vbo;
    pipe->clear = nvc0_clear;
    pipe->launch_grid = (nvc0->screen->base.class_3d >= NVE4_3D_CLASS) ?
                        nve4_launch_grid : nvc0_launch_grid;

    pipe->flush = nvc0_flush;
    pipe->texture_barrier = nvc0_texture_barrier;
    pipe->memory_barrier = nvc0_memory_barrier;
    pipe->get_sample_position = nvc0_context_get_sample_position;

    nouveau_context_init(&nvc0->base);
    nvc0_init_query_functions(nvc0);
    nvc0_init_surface_functions(nvc0);
    nvc0_init_state_functions(nvc0);
    nvc0_init_transfer_functions(nvc0);
    nvc0_init_resource_functions(pipe);

    nvc0->base.invalidate_resource_storage = nvc0_invalidate_resource_storage;

    pipe->create_video_codec = nvc0_create_decoder;
    pipe->create_video_buffer = nvc0_video_buffer_create;

    /* shader builtin library is per-screen, but we need a context for m2mf */
    nvc0_program_library_upload(nvc0);
    nvc0_program_init_tcp_empty(nvc0);
    if (!nvc0->tcp_empty)
        goto out_err;
    /* set the empty tctl prog on next draw in case one is never set */
    nvc0->dirty |= NVC0_NEW_TCTLPROG;

    /* now that there are no more opportunities for errors, set the current
     * context if there isn't already one.
     */
    if (!screen->cur_ctx) {
        nvc0->state = screen->save_state;
        screen->cur_ctx = nvc0;
        nouveau_pushbuf_bufctx(screen->base.pushbuf, nvc0->bufctx);
    }
    screen->base.pushbuf->kick_notify = nvc0_default_kick_notify;

    /* add permanently resident buffers to bufctxts */

    flags = NV_VRAM_DOMAIN(&screen->base) | NOUVEAU_BO_RD;

    BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->text);
    BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->uniform_bo);
    BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->txc);
    if (screen->compute) {
        BCTX_REFN_bo(nvc0->bufctx_cp, CP_SCREEN, flags, screen->text);
        BCTX_REFN_bo(nvc0->bufctx_cp, CP_SCREEN, flags, screen->txc);
        BCTX_REFN_bo(nvc0->bufctx_cp, CP_SCREEN, flags, screen->parm);
    }

    flags = NV_VRAM_DOMAIN(&screen->base) | NOUVEAU_BO_RDWR;

    if (screen->poly_cache)
        BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->poly_cache);
    if (screen->compute)
        BCTX_REFN_bo(nvc0->bufctx_cp, CP_SCREEN, flags, screen->tls);

    flags = NOUVEAU_BO_GART | NOUVEAU_BO_WR;

    BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->fence.bo);
    BCTX_REFN_bo(nvc0->bufctx, FENCE, flags, screen->fence.bo);
    if (screen->compute)
        BCTX_REFN_bo(nvc0->bufctx_cp, CP_SCREEN, flags, screen->fence.bo);

    nvc0->base.scratch.bo_size = 2 << 20;

    memset(nvc0->tex_handles, ~0, sizeof(nvc0->tex_handles));

    util_dynarray_init(&nvc0->global_residents);

    return pipe;

out_err:
    if (nvc0) {
        if (nvc0->bufctx_3d)
            nouveau_bufctx_del(&nvc0->bufctx_3d);
        if (nvc0->bufctx_cp)
            nouveau_bufctx_del(&nvc0->bufctx_cp);
        if (nvc0->bufctx)
            nouveau_bufctx_del(&nvc0->bufctx);
        FREE(nvc0->blit);
        FREE(nvc0);
    }
    return NULL;
}
Ejemplo n.º 8
0
struct pipe_context *
nvc0_create(struct pipe_screen *pscreen, void *priv)
{
   struct nvc0_screen *screen = nvc0_screen(pscreen);
   struct nvc0_context *nvc0;
   struct pipe_context *pipe;
   int ret;
   uint32_t flags;

   nvc0 = CALLOC_STRUCT(nvc0_context);
   if (!nvc0)
      return NULL;
   pipe = &nvc0->base.pipe;

   if (!nvc0_blitctx_create(nvc0))
      goto out_err;

   nvc0->base.pushbuf = screen->base.pushbuf;
   nvc0->base.client = screen->base.client;

   ret = nouveau_bufctx_new(screen->base.client, 2, &nvc0->bufctx);
   if (!ret)
      ret = nouveau_bufctx_new(screen->base.client, NVC0_BIND_3D_COUNT,
                               &nvc0->bufctx_3d);
   if (!ret)
      ret = nouveau_bufctx_new(screen->base.client, NVC0_BIND_CP_COUNT,
                               &nvc0->bufctx_cp);
   if (ret)
      goto out_err;

   nvc0->screen = screen;
   nvc0->base.screen = &screen->base;

   pipe->screen = pscreen;
   pipe->priv = priv;

   pipe->destroy = nvc0_destroy;

   pipe->draw_vbo = nvc0_draw_vbo;
   pipe->clear = nvc0_clear;
   pipe->launch_grid = (nvc0->screen->base.class_3d >= NVE4_3D_CLASS) ?
      nve4_launch_grid : nvc0_launch_grid;

   pipe->flush = nvc0_flush;
   pipe->texture_barrier = nvc0_texture_barrier;
   pipe->memory_barrier = nvc0_memory_barrier;
   pipe->get_sample_position = nvc0_context_get_sample_position;

   if (!screen->cur_ctx) {
      screen->cur_ctx = nvc0;
      nouveau_pushbuf_bufctx(screen->base.pushbuf, nvc0->bufctx);
   }
   screen->base.pushbuf->kick_notify = nvc0_default_kick_notify;

   nvc0_init_query_functions(nvc0);
   nvc0_init_surface_functions(nvc0);
   nvc0_init_state_functions(nvc0);
   nvc0_init_transfer_functions(nvc0);
   nvc0_init_resource_functions(pipe);

   nvc0->base.invalidate_resource_storage = nvc0_invalidate_resource_storage;

#ifdef NVC0_WITH_DRAW_MODULE
   /* no software fallbacks implemented */
   nvc0->draw = draw_create(pipe);
   assert(nvc0->draw);
   draw_set_rasterize_stage(nvc0->draw, nvc0_draw_render_stage(nvc0));
#endif

   pipe->create_video_codec = nvc0_create_decoder;
   pipe->create_video_buffer = nvc0_video_buffer_create;

   /* shader builtin library is per-screen, but we need a context for m2mf */
   nvc0_program_library_upload(nvc0);

   /* add permanently resident buffers to bufctxts */

   flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD;

   BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->text);
   BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->uniform_bo);
   BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->txc);
   if (screen->compute) {
      BCTX_REFN_bo(nvc0->bufctx_cp, CP_SCREEN, flags, screen->text);
      BCTX_REFN_bo(nvc0->bufctx_cp, CP_SCREEN, flags, screen->txc);
      BCTX_REFN_bo(nvc0->bufctx_cp, CP_SCREEN, flags, screen->parm);
   }

   flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR;

   if (screen->poly_cache)
      BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->poly_cache);
   if (screen->compute)
      BCTX_REFN_bo(nvc0->bufctx_cp, CP_SCREEN, flags, screen->tls);

   flags = NOUVEAU_BO_GART | NOUVEAU_BO_WR;

   BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->fence.bo);
   BCTX_REFN_bo(nvc0->bufctx, FENCE, flags, screen->fence.bo);
   if (screen->compute)
      BCTX_REFN_bo(nvc0->bufctx_cp, CP_SCREEN, flags, screen->fence.bo);

   nvc0->base.scratch.bo_size = 2 << 20;

   memset(nvc0->tex_handles, ~0, sizeof(nvc0->tex_handles));

   util_dynarray_init(&nvc0->global_residents);

   return pipe;

out_err:
   if (nvc0) {
      if (nvc0->bufctx_3d)
         nouveau_bufctx_del(&nvc0->bufctx_3d);
      if (nvc0->bufctx_cp)
         nouveau_bufctx_del(&nvc0->bufctx_cp);
      if (nvc0->bufctx)
         nouveau_bufctx_del(&nvc0->bufctx);
      if (nvc0->blit)
         FREE(nvc0->blit);
      FREE(nvc0);
   }
   return NULL;
}
Ejemplo n.º 9
0
int
nvc0_screen_get_driver_query_group_info(struct pipe_screen *pscreen,
                                        unsigned id,
                                        struct pipe_driver_query_group_info *info)
{
   struct nvc0_screen *screen = nvc0_screen(pscreen);
   int count = 0;

#ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
   count++;
#endif

   if (screen->base.device->drm_version >= 0x01000101) {
      if (screen->compute) {
         if (screen->base.class_3d == NVE4_3D_CLASS) {
            count += 2;
         } else
         if (screen->base.class_3d < NVE4_3D_CLASS) {
            count += 2;
         }
      }
   }

   if (!info)
      return count;

   if (id == NVC0_HW_SM_QUERY_GROUP) {
      if (screen->compute) {
         info->name = "MP counters";

         /* Because we can't expose the number of hardware counters needed for
          * each different query, we don't want to allow more than one active
          * query simultaneously to avoid failure when the maximum number of
          * counters is reached. Note that these groups of GPU counters are
          * currently only used by AMD_performance_monitor.
          */
         info->max_active_queries = 1;

         if (screen->base.class_3d == NVE4_3D_CLASS) {
            info->num_queries = NVE4_HW_SM_QUERY_COUNT;
            return 1;
         } else
         if (screen->base.class_3d < NVE4_3D_CLASS) {
            info->num_queries = NVC0_HW_SM_QUERY_COUNT;
            return 1;
         }
      }
   } else
   if (id == NVC0_HW_METRIC_QUERY_GROUP) {
      if (screen->compute) {
          if (screen->base.class_3d == NVE4_3D_CLASS) {
            info->name = "Performance metrics";
            info->max_active_queries = 1;
            info->num_queries = NVE4_HW_METRIC_QUERY_COUNT;
            return 1;
         } else
         if (screen->base.class_3d < NVE4_3D_CLASS) {
            info->name = "Performance metrics";
            info->max_active_queries = 1;
            info->num_queries = NVC0_HW_METRIC_QUERY_COUNT;
            return 1;
         }
      }
   }
#ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
   else if (id == NVC0_SW_QUERY_DRV_STAT_GROUP) {
      info->name = "Driver statistics";
      info->max_active_queries = NVC0_SW_QUERY_DRV_STAT_COUNT;
      info->num_queries = NVC0_SW_QUERY_DRV_STAT_COUNT;
      return 1;
   }
#endif

   /* user asked for info about non-existing query group */
   info->name = "this_is_not_the_query_group_you_are_looking_for";
   info->max_active_queries = 0;
   info->num_queries = 0;
   return 0;
}
Ejemplo n.º 10
0
struct pipe_context *
nvc0_create(struct pipe_screen *pscreen, void *priv)
{
   struct nvc0_screen *screen = nvc0_screen(pscreen);
   struct nvc0_context *nvc0;
   struct pipe_context *pipe;
   int ret;
   uint32_t flags;

   nvc0 = CALLOC_STRUCT(nvc0_context);
   if (!nvc0)
      return NULL;
   pipe = &nvc0->base.pipe;

   nvc0->base.pushbuf = screen->base.pushbuf;

   ret = nouveau_bufctx_new(screen->base.client, NVC0_BIND_COUNT,
                            &nvc0->bufctx_3d);
   if (!ret)
      nouveau_bufctx_new(screen->base.client, 2, &nvc0->bufctx);
   if (ret)
      goto out_err;

   nvc0->screen = screen;
   nvc0->base.screen = &screen->base;

   pipe->screen = pscreen;
   pipe->priv = priv;

   pipe->destroy = nvc0_destroy;

   pipe->draw_vbo = nvc0_draw_vbo;
   pipe->clear = nvc0_clear;

   pipe->flush = nvc0_flush;
   pipe->texture_barrier = nvc0_texture_barrier;

   if (!screen->cur_ctx) {
      screen->cur_ctx = nvc0;
      nouveau_pushbuf_bufctx(screen->base.pushbuf, nvc0->bufctx);
   }
   screen->base.pushbuf->kick_notify = nvc0_default_kick_notify;

   nvc0_init_query_functions(nvc0);
   nvc0_init_surface_functions(nvc0);
   nvc0_init_state_functions(nvc0);
   nvc0_init_transfer_functions(nvc0);
   nvc0_init_resource_functions(pipe);

#ifdef NVC0_WITH_DRAW_MODULE
   /* no software fallbacks implemented */
   nvc0->draw = draw_create(pipe);
   assert(nvc0->draw);
   draw_set_rasterize_stage(nvc0->draw, nvc0_draw_render_stage(nvc0));
#endif

   nouveau_context_init_vdec(&nvc0->base);

   /* shader builtin library is per-screen, but we need a context for m2mf */
   nvc0_program_library_upload(nvc0);

   /* add permanently resident buffers to bufctxts */

   flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD;

   BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->text);
   BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->uniform_bo);
   BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->txc);

   flags = NOUVEAU_BO_GART | NOUVEAU_BO_WR;

   BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->fence.bo);
   BCTX_REFN_bo(nvc0->bufctx, FENCE, flags, screen->fence.bo);

   nvc0->base.scratch.bo_size = 2 << 20;

   return pipe;

out_err:
   if (nvc0) {
      if (nvc0->bufctx_3d)
         nouveau_bufctx_del(&nvc0->bufctx_3d);
      if (nvc0->bufctx)
         nouveau_bufctx_del(&nvc0->bufctx);
      FREE(nvc0);
   }
   return NULL;
}