loader: allocate VRAM in display GPU in case of prime
authorYogesh Mohanmarimuthu <yogesh.mohanmarimuthu@amd.com>
Mon, 3 May 2021 18:22:40 +0000 (23:52 +0530)
committerMarge Bot <eric+marge@anholt.net>
Thu, 3 Jun 2021 09:12:32 +0000 (09:12 +0000)
Allocates VRAM in display GPU in case of prime. Then the dma_buf is imported
into prime GPU.

v2: add comments to make code more readable (Pierre-Eric)
    removed if check limiting p2p only for matching driver name
v3: keep old path for non mesa driver (Michel Dänzer)
v4: destroy linear_buffer_display_gpu after import (Michel Dänzer)
    fall back if linear_buffer_display_gpu alloc fail (Michel Dänzer)

Signed-off-by: Yogesh Mohanmarimuthu <yogesh.mohanmarimuthu@amd.com>
Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10595>

src/loader/loader_dri3_helper.c
src/loader/loader_dri3_helper.h

index c5e340e..6428ee5 100644 (file)
@@ -1309,7 +1309,7 @@ dri3_alloc_render_buffer(struct loader_dri3_drawable *draw, unsigned int format,
                          int width, int height, int depth)
 {
    struct loader_dri3_buffer *buffer;
-   __DRIimage *pixmap_buffer;
+   __DRIimage *pixmap_buffer = NULL, *linear_buffer_display_gpu = NULL;
    xcb_pixmap_t pixmap;
    xcb_sync_fence_t sync_fence;
    struct xshmfence *shm_fence;
@@ -1422,18 +1422,37 @@ dri3_alloc_render_buffer(struct loader_dri3_drawable *draw, unsigned int format,
       if (!buffer->image)
          goto no_image;
 
-      buffer->linear_buffer =
-        draw->ext->image->createImage(draw->dri_screen,
-                                      width, height,
-                                      dri3_linear_format_for_format(draw, format),
-                                      __DRI_IMAGE_USE_SHARE |
-                                      __DRI_IMAGE_USE_LINEAR |
-                                      __DRI_IMAGE_USE_BACKBUFFER,
-                                      buffer);
-      pixmap_buffer = buffer->linear_buffer;
+      /* if driver name is same only then dri_screen_display_gpu is set.
+       * This check is needed because for simplicity render gpu image extension
+       * is also used for display gpu.
+       */
+      if (draw->dri_screen_display_gpu) {
+         linear_buffer_display_gpu =
+           draw->ext->image->createImage(draw->dri_screen_display_gpu,
+                                         width, height,
+                                         dri3_linear_format_for_format(draw, format),
+                                         __DRI_IMAGE_USE_SHARE |
+                                         __DRI_IMAGE_USE_LINEAR |
+                                         __DRI_IMAGE_USE_BACKBUFFER,
+                                         buffer);
+         pixmap_buffer = linear_buffer_display_gpu;
+      }
 
-      if (!buffer->linear_buffer)
-         goto no_linear_buffer;
+      if (!pixmap_buffer) {
+         buffer->linear_buffer =
+           draw->ext->image->createImage(draw->dri_screen,
+                                         width, height,
+                                         dri3_linear_format_for_format(draw, format),
+                                         __DRI_IMAGE_USE_SHARE |
+                                         __DRI_IMAGE_USE_LINEAR |
+                                         __DRI_IMAGE_USE_BACKBUFFER,
+                                         buffer);
+
+         pixmap_buffer = buffer->linear_buffer;
+         if (!buffer->linear_buffer) {
+            goto no_linear_buffer;
+         }
+      }
    }
 
    /* X want some information about the planes, so ask the image for it
@@ -1475,6 +1494,26 @@ dri3_alloc_render_buffer(struct loader_dri3_drawable *draw, unsigned int format,
    if (!ret)
       buffer->modifier = DRM_FORMAT_MOD_INVALID;
 
+   if (draw->is_different_gpu && draw->dri_screen_display_gpu &&
+       linear_buffer_display_gpu) {
+      /* The linear buffer was created in the display GPU's vram, so we
+       * need to make it visible to render GPU
+       */
+      buffer->linear_buffer =
+         draw->ext->image->createImageFromFds(draw->dri_screen,
+                                              width,
+                                              height,
+                                              image_format_to_fourcc(format),
+                                              &buffer_fds[0], num_planes,
+                                              &buffer->strides[0],
+                                              &buffer->offsets[0],
+                                              buffer);
+      if (!buffer->linear_buffer)
+         goto no_buffer_attrib;
+
+      draw->ext->image->destroyImage(linear_buffer_display_gpu);
+   }
+
    pixmap = xcb_generate_id(draw->conn);
 #ifdef HAVE_DRI3_MODIFIERS
    if (draw->multiplanes_available &&
index a256c37..c70f114 100644 (file)
@@ -42,9 +42,15 @@ enum loader_dri3_buffer_type {
 
 struct loader_dri3_buffer {
    __DRIimage   *image;
-   __DRIimage   *linear_buffer;
    uint32_t     pixmap;
 
+   /* default case: linear buffer allocated in render gpu vram.
+    * p2p case: linear buffer allocated in display gpu vram and imported
+    *           to render gpu. p2p case is enabled when driver name matches
+    *           while creating screen in dri3_create_screen() function.
+    */
+   __DRIimage   *linear_buffer;
+
    /* Synchronization between the client and X server is done using an
     * xshmfence that is mapped into an X server SyncFence. This lets the
     * client check whether the X server is done using a buffer with a simple