radeonsi: move sid.h/r600d_common.h to a common place.
[mesa.git] / src / gallium / winsys / amdgpu / drm / amdgpu_cs.c
index 4a7302ab2cb095d943fe0a165b26e7ba68151557..73c8a9739ae7fee980adede9fd3729eeceb8db9c 100644 (file)
@@ -35,7 +35,7 @@
 #include <stdio.h>
 #include <amdgpu_drm.h>
 
-#include "../../../drivers/radeonsi/sid.h"
+#include "amd/common/sid.h"
 
 /* FENCES */
 
@@ -118,7 +118,7 @@ bool amdgpu_fence_wait(struct pipe_fence_handle *fence, uint64_t timeout,
                                    &expired);
    if (r) {
       fprintf(stderr, "amdgpu: amdgpu_cs_query_fence_status failed.\n");
-      return FALSE;
+      return false;
    }
 
    if (expired) {
@@ -137,6 +137,28 @@ static bool amdgpu_fence_wait_rel_timeout(struct radeon_winsys *rws,
    return amdgpu_fence_wait(fence, timeout, false);
 }
 
+static struct pipe_fence_handle *
+amdgpu_cs_get_next_fence(struct radeon_winsys_cs *rcs)
+{
+   struct amdgpu_cs *cs = amdgpu_cs(rcs);
+   struct pipe_fence_handle *fence = NULL;
+
+   if (cs->next_fence) {
+      amdgpu_fence_reference(&fence, cs->next_fence);
+      return fence;
+   }
+
+   fence = amdgpu_fence_create(cs->ctx,
+                               cs->csc->request.ip_type,
+                               cs->csc->request.ip_instance,
+                               cs->csc->request.ring);
+   if (!fence)
+      return NULL;
+
+   amdgpu_fence_reference(&cs->next_fence, fence);
+   return fence;
+}
+
 /* CONTEXTS */
 
 static struct radeon_winsys_ctx *amdgpu_ctx_create(struct radeon_winsys *ws)
@@ -227,9 +249,10 @@ static bool amdgpu_cs_has_user_fence(struct amdgpu_cs_context *cs)
           cs->request.ip_type != AMDGPU_HW_IP_VCE;
 }
 
-static bool amdgpu_cs_has_chaining(enum ring_type ring_type)
+static bool amdgpu_cs_has_chaining(struct amdgpu_cs *cs)
 {
-   return ring_type == RING_GFX;
+   return cs->ctx->ws->info.chip_class >= CIK &&
+          cs->ring_type == RING_GFX;
 }
 
 static unsigned amdgpu_cs_epilog_dws(enum ring_type ring_type)
@@ -343,9 +366,9 @@ static unsigned amdgpu_cs_add_buffer(struct radeon_winsys_cs *rcs,
                                      priority, &added_domains);
 
    if (added_domains & RADEON_DOMAIN_VRAM)
-      cs->csc->used_vram += bo->base.size;
+      cs->main.base.used_vram += bo->base.size;
    else if (added_domains & RADEON_DOMAIN_GTT)
-      cs->csc->used_gart += bo->base.size;
+      cs->main.base.used_gart += bo->base.size;
 
    return index;
 }
@@ -362,7 +385,7 @@ static bool amdgpu_ib_new_buffer(struct amdgpu_winsys *ws, struct amdgpu_ib *ib)
     * is the largest power of two that fits into the size field of the
     * INDIRECT_BUFFER packet.
     */
-   if (amdgpu_cs_has_chaining(amdgpu_cs_from_ib(ib)->ring_type))
+   if (amdgpu_cs_has_chaining(amdgpu_cs_from_ib(ib)))
       buffer_size = 4 *util_next_power_of_two(ib->max_ib_size);
    else
       buffer_size = 4 *util_next_power_of_two(4 * ib->max_ib_size);
@@ -455,7 +478,7 @@ static bool amdgpu_get_new_ib(struct radeon_winsys *ws, struct amdgpu_cs *cs,
       unreachable("unhandled IB type");
    }
 
-   if (!amdgpu_cs_has_chaining(cs->ring_type)) {
+   if (!amdgpu_cs_has_chaining(cs)) {
       ib_size = MAX2(ib_size,
                      4 * MIN2(util_next_power_of_two(ib->max_ib_size),
                               amdgpu_ib_max_submit_dwords(ib_type)));
@@ -497,8 +520,8 @@ static void amdgpu_ib_finalize(struct amdgpu_ib *ib)
    ib->max_ib_size = MAX2(ib->max_ib_size, ib->base.prev_dw + ib->base.current.cdw);
 }
 
-static boolean amdgpu_init_cs_context(struct amdgpu_cs_context *cs,
-                                      enum ring_type ring_type)
+static bool amdgpu_init_cs_context(struct amdgpu_cs_context *cs,
+                                   enum ring_type ring_type)
 {
    int i;
 
@@ -529,20 +552,20 @@ static boolean amdgpu_init_cs_context(struct amdgpu_cs_context *cs,
    cs->buffers = (struct amdgpu_cs_buffer*)
                   CALLOC(1, cs->max_num_buffers * sizeof(struct amdgpu_cs_buffer));
    if (!cs->buffers) {
-      return FALSE;
+      return false;
    }
 
    cs->handles = CALLOC(1, cs->max_num_buffers * sizeof(amdgpu_bo_handle));
    if (!cs->handles) {
       FREE(cs->buffers);
-      return FALSE;
+      return false;
    }
 
    cs->flags = CALLOC(1, cs->max_num_buffers);
    if (!cs->flags) {
       FREE(cs->handles);
       FREE(cs->buffers);
-      return FALSE;
+      return false;
    }
 
    for (i = 0; i < ARRAY_SIZE(cs->buffer_indices_hashlist); i++) {
@@ -556,7 +579,7 @@ static boolean amdgpu_init_cs_context(struct amdgpu_cs_context *cs,
    cs->ib[IB_CONST_PREAMBLE].flags = AMDGPU_IB_FLAG_CE |
                                      AMDGPU_IB_FLAG_PREAMBLE;
 
-   return TRUE;
+   return true;
 }
 
 static void amdgpu_cs_context_cleanup(struct amdgpu_cs_context *cs)
@@ -571,8 +594,6 @@ static void amdgpu_cs_context_cleanup(struct amdgpu_cs_context *cs)
    }
 
    cs->num_buffers = 0;
-   cs->used_gart = 0;
-   cs->used_vram = 0;
    amdgpu_fence_reference(&cs->fence, NULL);
 
    for (i = 0; i < ARRAY_SIZE(cs->buffer_indices_hashlist); i++) {
@@ -698,9 +719,9 @@ static int amdgpu_cs_lookup_buffer(struct radeon_winsys_cs *rcs,
    return amdgpu_lookup_buffer(cs->csc, (struct amdgpu_winsys_bo*)buf);
 }
 
-static boolean amdgpu_cs_validate(struct radeon_winsys_cs *rcs)
+static bool amdgpu_cs_validate(struct radeon_winsys_cs *rcs)
 {
-   return TRUE;
+   return true;
 }
 
 static bool amdgpu_cs_check_space(struct radeon_winsys_cs *rcs, unsigned dw)
@@ -721,7 +742,7 @@ static bool amdgpu_cs_check_space(struct radeon_winsys_cs *rcs, unsigned dw)
    if (rcs->current.max_dw - rcs->current.cdw >= dw)
       return true;
 
-   if (!amdgpu_cs_has_chaining(cs->ring_type))
+   if (!amdgpu_cs_has_chaining(cs))
       return false;
 
    /* Allocate a new chunk */
@@ -784,29 +805,6 @@ static bool amdgpu_cs_check_space(struct radeon_winsys_cs *rcs, unsigned dw)
    return true;
 }
 
-static boolean amdgpu_cs_memory_below_limit(struct radeon_winsys_cs *rcs, uint64_t vram, uint64_t gtt)
-{
-   struct amdgpu_cs *cs = amdgpu_cs(rcs);
-   struct amdgpu_winsys *ws = cs->ctx->ws;
-
-   vram += cs->csc->used_vram;
-   gtt += cs->csc->used_gart;
-
-   /* Anything that goes above the VRAM size should go to GTT. */
-   if (vram > ws->info.vram_size)
-       gtt += vram - ws->info.vram_size;
-
-   /* Now we just need to check if we have enough GTT. */
-   return gtt < ws->info.gart_size * 0.7;
-}
-
-static uint64_t amdgpu_cs_query_memory_usage(struct radeon_winsys_cs *rcs)
-{
-   struct amdgpu_cs_context *cs = amdgpu_cs(rcs)->csc;
-
-   return cs->used_vram + cs->used_gart;
-}
-
 static unsigned amdgpu_cs_get_buffer_list(struct radeon_winsys_cs *rcs,
                                           struct radeon_bo_list_item *list)
 {
@@ -815,7 +813,7 @@ static unsigned amdgpu_cs_get_buffer_list(struct radeon_winsys_cs *rcs,
 
     if (list) {
         for (i = 0; i < cs->num_buffers; i++) {
-            pb_reference(&list[i].buf, &cs->buffers[i].bo->base);
+            list[i].bo_size = cs->buffers[i].bo->base.size;
             list[i].vm_address = cs->buffers[i].bo->va;
             list[i].priority_usage = cs->buffers[i].priority_usage;
         }
@@ -823,7 +821,7 @@ static unsigned amdgpu_cs_get_buffer_list(struct radeon_winsys_cs *rcs,
     return cs->num_buffers;
 }
 
-DEBUG_GET_ONCE_BOOL_OPTION(all_bos, "RADEON_ALL_BOS", FALSE)
+DEBUG_GET_ONCE_BOOL_OPTION(all_bos, "RADEON_ALL_BOS", false)
 
 /* Since the kernel driver doesn't synchronize execution between different
  * rings automatically, we have to add fence dependencies manually.
@@ -872,7 +870,7 @@ static void amdgpu_add_fence_dependencies(struct amdgpu_cs *acs)
    }
 }
 
-void amdgpu_cs_submit_ib(void *job)
+void amdgpu_cs_submit_ib(void *job, int thread_index)
 {
    struct amdgpu_cs *acs = (struct amdgpu_cs*)job;
    struct amdgpu_winsys *ws = acs->ctx->ws;
@@ -899,6 +897,7 @@ void amdgpu_cs_submit_ib(void *job)
       if (!handles) {
          pipe_mutex_unlock(ws->global_bo_list_lock);
          amdgpu_cs_context_cleanup(cs);
+         cs->error_code = -ENOMEM;
          return;
       }
 
@@ -922,16 +921,18 @@ void amdgpu_cs_submit_ib(void *job)
       fprintf(stderr, "amdgpu: buffer list creation failed (%d)\n", r);
       cs->request.resources = NULL;
       amdgpu_fence_signalled(cs->fence);
+      cs->error_code = r;
       goto cleanup;
    }
 
    r = amdgpu_cs_submit(acs->ctx->ctx, 0, &cs->request, 1);
+   cs->error_code = r;
    if (r) {
       if (r == -ENOMEM)
          fprintf(stderr, "amdgpu: Not enough memory for command submission.\n");
       else
          fprintf(stderr, "amdgpu: The CS has been rejected, "
-                 "see dmesg for more information.\n");
+                 "see dmesg for more information (%i).\n", r);
 
       amdgpu_fence_signalled(cs->fence);
    } else {
@@ -965,27 +966,38 @@ void amdgpu_cs_sync_flush(struct radeon_winsys_cs *rcs)
       util_queue_job_wait(&cs->flush_completed);
 }
 
-DEBUG_GET_ONCE_BOOL_OPTION(noop, "RADEON_NOOP", FALSE)
+DEBUG_GET_ONCE_BOOL_OPTION(noop, "RADEON_NOOP", false)
 
-static void amdgpu_cs_flush(struct radeon_winsys_cs *rcs,
-                            unsigned flags,
-                            struct pipe_fence_handle **fence)
+static int amdgpu_cs_flush(struct radeon_winsys_cs *rcs,
+                           unsigned flags,
+                           struct pipe_fence_handle **fence)
 {
    struct amdgpu_cs *cs = amdgpu_cs(rcs);
    struct amdgpu_winsys *ws = cs->ctx->ws;
+   int error_code = 0;
 
    rcs->current.max_dw += amdgpu_cs_epilog_dws(cs->ring_type);
 
    switch (cs->ring_type) {
    case RING_DMA:
       /* pad DMA ring to 8 DWs */
-      while (rcs->current.cdw & 7)
-         OUT_CS(rcs, 0x00000000); /* NOP packet */
+      if (ws->info.chip_class <= SI) {
+         while (rcs->current.cdw & 7)
+            OUT_CS(rcs, 0xf0000000); /* NOP packet */
+      } else {
+         while (rcs->current.cdw & 7)
+            OUT_CS(rcs, 0x00000000); /* NOP packet */
+      }
       break;
    case RING_GFX:
       /* pad GFX ring to 8 DWs to meet CP fetch alignment requirements */
-      while (rcs->current.cdw & 7)
-         OUT_CS(rcs, 0xffff1000); /* type3 nop packet */
+      if (ws->info.gfx_ib_pad_with_type2) {
+         while (rcs->current.cdw & 7)
+            OUT_CS(rcs, 0x80000000); /* type2 nop packet */
+      } else {
+         while (rcs->current.cdw & 7)
+            OUT_CS(rcs, 0xffff1000); /* type3 nop packet */
+      }
 
       /* Also pad the const IB. */
       if (cs->const_ib.ib_mapped)
@@ -1026,10 +1038,16 @@ static void amdgpu_cs_flush(struct radeon_winsys_cs *rcs,
 
       /* Create a fence. */
       amdgpu_fence_reference(&cur->fence, NULL);
-      cur->fence = amdgpu_fence_create(cs->ctx,
-                                           cur->request.ip_type,
-                                           cur->request.ip_instance,
-                                           cur->request.ring);
+      if (cs->next_fence) {
+         /* just move the reference */
+         cur->fence = cs->next_fence;
+         cs->next_fence = NULL;
+      } else {
+         cur->fence = amdgpu_fence_create(cs->ctx,
+                                          cur->request.ip_type,
+                                          cur->request.ip_instance,
+                                          cur->request.ring);
+      }
       if (fence)
          amdgpu_fence_reference(fence, cur->fence);
 
@@ -1052,9 +1070,11 @@ static void amdgpu_cs_flush(struct radeon_winsys_cs *rcs,
       /* Submit. */
       if ((flags & RADEON_FLUSH_ASYNC) &&
           util_queue_is_initialized(&ws->cs_queue)) {
-         util_queue_add_job(&ws->cs_queue, cs, &cs->flush_completed);
+         util_queue_add_job(&ws->cs_queue, cs, &cs->flush_completed,
+                            amdgpu_cs_submit_ib, NULL);
       } else {
-         amdgpu_cs_submit_ib(cs);
+         amdgpu_cs_submit_ib(cs, 0);
+         error_code = cs->cst->error_code;
       }
    } else {
       amdgpu_cs_context_cleanup(cs->csc);
@@ -1066,7 +1086,11 @@ static void amdgpu_cs_flush(struct radeon_winsys_cs *rcs,
    if (cs->const_preamble_ib.ib_mapped)
       amdgpu_get_new_ib(&ws->base, cs, IB_CONST_PREAMBLE);
 
+   cs->main.base.used_gart = 0;
+   cs->main.base.used_vram = 0;
+
    ws->num_cs_flushes++;
+   return error_code;
 }
 
 static void amdgpu_cs_destroy(struct radeon_winsys_cs *rcs)
@@ -1084,12 +1108,13 @@ static void amdgpu_cs_destroy(struct radeon_winsys_cs *rcs)
    FREE(cs->const_preamble_ib.base.prev);
    amdgpu_destroy_cs_context(&cs->csc1);
    amdgpu_destroy_cs_context(&cs->csc2);
+   amdgpu_fence_reference(&cs->next_fence, NULL);
    FREE(cs);
 }
 
-static boolean amdgpu_bo_is_referenced(struct radeon_winsys_cs *rcs,
-                                       struct pb_buffer *_buf,
-                                       enum radeon_bo_usage usage)
+static bool amdgpu_bo_is_referenced(struct radeon_winsys_cs *rcs,
+                                    struct pb_buffer *_buf,
+                                    enum radeon_bo_usage usage)
 {
    struct amdgpu_cs *cs = amdgpu_cs(rcs);
    struct amdgpu_winsys_bo *bo = (struct amdgpu_winsys_bo*)_buf;
@@ -1110,10 +1135,9 @@ void amdgpu_cs_init_functions(struct amdgpu_winsys *ws)
    ws->base.cs_lookup_buffer = amdgpu_cs_lookup_buffer;
    ws->base.cs_validate = amdgpu_cs_validate;
    ws->base.cs_check_space = amdgpu_cs_check_space;
-   ws->base.cs_memory_below_limit = amdgpu_cs_memory_below_limit;
-   ws->base.cs_query_memory_usage = amdgpu_cs_query_memory_usage;
    ws->base.cs_get_buffer_list = amdgpu_cs_get_buffer_list;
    ws->base.cs_flush = amdgpu_cs_flush;
+   ws->base.cs_get_next_fence = amdgpu_cs_get_next_fence;
    ws->base.cs_is_buffer_referenced = amdgpu_bo_is_referenced;
    ws->base.cs_sync_flush = amdgpu_cs_sync_flush;
    ws->base.fence_wait = amdgpu_fence_wait_rel_timeout;