Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 2012-2013 LunarG, Inc.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the "Software"),
  8.  * to deal in the Software without restriction, including without limitation
  9.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10.  * and/or sell copies of the Software, and to permit persons to whom the
  11.  * Software is furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be included
  14.  * in all copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  22.  * DEALINGS IN THE SOFTWARE.
  23.  *
  24.  * Authors:
  25.  *    Chia-I Wu <olv@lunarg.com>
  26.  */
  27.  
  28. #include "core/ilo_builder_mi.h"
  29. #include "core/intel_winsys.h"
  30.  
  31. #include "ilo_shader.h"
  32. #include "ilo_cp.h"
  33.  
  34. static const struct ilo_cp_owner ilo_cp_default_owner;
  35.  
  36. static void
  37. ilo_cp_release_owner(struct ilo_cp *cp)
  38. {
  39.    if (cp->owner != &ilo_cp_default_owner) {
  40.       const struct ilo_cp_owner *owner = cp->owner;
  41.  
  42.       cp->owner = &ilo_cp_default_owner;
  43.  
  44.       assert(ilo_cp_space(cp) >= owner->reserve);
  45.       owner->release(cp, owner->data);
  46.    }
  47. }
  48.  
  49. /**
  50.  * Set the parser owner.  If this is a new owner or a new ring, the old owner
  51.  * is released and the new owner's own() is called.  The parser may implicitly
  52.  * submit if there is a ring change.
  53.  *
  54.  * own() is called before \p owner owns the parser.  It must make sure there
  55.  * is more space than \p owner->reserve when it returns.  Calling
  56.  * ilo_cp_submit() is allowed.
  57.  *
  58.  * release() will be called after \p owner loses the parser.  That may happen
  59.  * just before the parser submits and ilo_cp_submit() is not allowed.
  60.  */
  61. void
  62. ilo_cp_set_owner(struct ilo_cp *cp, enum intel_ring_type ring,
  63.                  const struct ilo_cp_owner *owner)
  64. {
  65.    if (!owner)
  66.       owner = &ilo_cp_default_owner;
  67.  
  68.    if (cp->ring != ring) {
  69.       ilo_cp_submit(cp, "ring change");
  70.       cp->ring = ring;
  71.    }
  72.  
  73.    if (cp->owner != owner) {
  74.       ilo_cp_release_owner(cp);
  75.  
  76.       owner->own(cp, owner->data);
  77.  
  78.       assert(ilo_cp_space(cp) >= owner->reserve);
  79.       cp->owner = owner;
  80.    }
  81. }
  82.  
  83. static struct intel_bo *
  84. ilo_cp_end_batch(struct ilo_cp *cp, unsigned *used)
  85. {
  86.    struct intel_bo *bo;
  87.  
  88.    ilo_cp_release_owner(cp);
  89.  
  90.    if (!ilo_builder_batch_used(&cp->builder)) {
  91.       ilo_builder_batch_discard(&cp->builder);
  92.       return NULL;
  93.    }
  94.  
  95.    /* see ilo_cp_space() */
  96.    assert(ilo_builder_batch_space(&cp->builder) >= 2);
  97.    gen6_mi_batch_buffer_end(&cp->builder);
  98.  
  99.    bo = ilo_builder_end(&cp->builder, used);
  100.  
  101.    /* we have to assume that kernel uploads also failed */
  102.    if (!bo)
  103.       ilo_shader_cache_invalidate(cp->shader_cache);
  104.  
  105.    return bo;
  106. }
  107.  
  108. static bool
  109. ilo_cp_detect_hang(struct ilo_cp *cp)
  110. {
  111.    uint32_t active_lost, pending_lost;
  112.    bool guilty = false;
  113.  
  114.    if (likely(!(ilo_debug & ILO_DEBUG_HANG)))
  115.       return false;
  116.  
  117.    /* wait and get reset stats */
  118.    if (intel_bo_wait(cp->last_submitted_bo, -1) ||
  119.        intel_winsys_get_reset_stats(cp->winsys, cp->render_ctx,
  120.           &active_lost, &pending_lost))
  121.       return false;
  122.  
  123.    if (cp->active_lost != active_lost) {
  124.       ilo_err("GPU hang caused by bo %p\n", cp->last_submitted_bo);
  125.       cp->active_lost = active_lost;
  126.       guilty = true;
  127.    }
  128.  
  129.    if (cp->pending_lost != pending_lost) {
  130.       ilo_err("GPU hang detected\n");
  131.       cp->pending_lost = pending_lost;
  132.    }
  133.  
  134.    return guilty;
  135. }
  136.  
  137. /**
  138.  * Flush the command parser and execute the commands.  When the parser buffer
  139.  * is empty, the callback is not invoked.
  140.  */
  141. void
  142. ilo_cp_submit_internal(struct ilo_cp *cp)
  143. {
  144.    const bool do_exec = !(ilo_debug & ILO_DEBUG_NOHW);
  145.    struct intel_bo *bo;
  146.    unsigned used;
  147.    int err;
  148.  
  149.    bo = ilo_cp_end_batch(cp, &used);
  150.    if (!bo)
  151.       return;
  152.  
  153.    if (likely(do_exec)) {
  154.       err = intel_winsys_submit_bo(cp->winsys, cp->ring,
  155.             bo, used, cp->render_ctx, cp->one_off_flags);
  156.    }
  157.    else {
  158.       err = 0;
  159.    }
  160.  
  161.    cp->one_off_flags = 0;
  162.  
  163.    if (!err) {
  164.       bool guilty;
  165.  
  166.       intel_bo_unref(cp->last_submitted_bo);
  167.       cp->last_submitted_bo = intel_bo_ref(bo);
  168.  
  169.       guilty = ilo_cp_detect_hang(cp);
  170.  
  171.       if (unlikely((ilo_debug & ILO_DEBUG_BATCH) || guilty)) {
  172.          ilo_builder_decode(&cp->builder);
  173.          if (guilty)
  174.             abort();
  175.       }
  176.  
  177.       if (cp->submit_callback)
  178.          cp->submit_callback(cp, cp->submit_callback_data);
  179.    }
  180.  
  181.    ilo_builder_begin(&cp->builder);
  182. }
  183.  
  184. /**
  185.  * Destroy the command parser.
  186.  */
  187. void
  188. ilo_cp_destroy(struct ilo_cp *cp)
  189. {
  190.    ilo_builder_reset(&cp->builder);
  191.  
  192.    intel_winsys_destroy_context(cp->winsys, cp->render_ctx);
  193.    FREE(cp);
  194. }
  195.  
  196. /**
  197.  * Create a command parser.
  198.  */
  199. struct ilo_cp *
  200. ilo_cp_create(const struct ilo_dev *dev,
  201.               struct intel_winsys *winsys,
  202.               struct ilo_shader_cache *shc)
  203. {
  204.    struct ilo_cp *cp;
  205.  
  206.    cp = CALLOC_STRUCT(ilo_cp);
  207.    if (!cp)
  208.       return NULL;
  209.  
  210.    cp->winsys = winsys;
  211.    cp->shader_cache = shc;
  212.    cp->render_ctx = intel_winsys_create_context(winsys);
  213.    if (!cp->render_ctx) {
  214.       FREE(cp);
  215.       return NULL;
  216.    }
  217.  
  218.    cp->ring = INTEL_RING_RENDER;
  219.    cp->owner = &ilo_cp_default_owner;
  220.  
  221.    ilo_builder_init(&cp->builder, dev, winsys);
  222.  
  223.    if (!ilo_builder_begin(&cp->builder)) {
  224.       ilo_cp_destroy(cp);
  225.       return NULL;
  226.    }
  227.  
  228.    return cp;
  229. }
  230.