[Mesa-dev] [PATCH] [rfc] radv: add initial prime support.

Mike Lothian mike at fireburn.co.uk
Wed Nov 23 08:48:20 UTC 2016


You are a star :D

I'll test this out tonight

On Wed, 23 Nov 2016 at 05:29 Dave Airlie <airlied at gmail.com> wrote:

> From: Dave Airlie <airlied at redhat.com>
>
> This is kind of a gross hacks, but vulkan doesn't specify anything
> but it would be nice to let people with prime systems at least
> see some stuff rendering for now.
>
> This creates a linear shadow image in GART that gets blitted to at the
> image transition.
>
> Now ideally:
> this would use SDMA - but we want to use SDMA for transfer queues
> maybe we don't expose a transfer queue on prime cards who knows.
>
> we wouldn't have to add two pointers to every image, but my other
> attempts at this were ugly.
>
> Is the image transition the proper place to hack this in? not
> really sure anywhere else is appropriate.
>
> It also relies on DRI_PRIME=1 being set, I should be able
> to work this out somehow automatically I think, probably getting
> a DRI3 fd from the X server and doing drmGetDevice on it, and
> comparing where we end up.
>
> Signed-off-by: Dave Airlie <airlied at redhat.com>
> ---
>  src/amd/vulkan/radv_cmd_buffer.c |  18 +++++++
>  src/amd/vulkan/radv_device.c     |   3 ++
>  src/amd/vulkan/radv_meta.h       |   2 +
>  src/amd/vulkan/radv_meta_copy.c  |  31 +++++++++++
>  src/amd/vulkan/radv_private.h    |   4 ++
>  src/amd/vulkan/radv_wsi.c        | 111
> ++++++++++++++++++++++++++++++---------
>  6 files changed, 144 insertions(+), 25 deletions(-)
>
> diff --git a/src/amd/vulkan/radv_cmd_buffer.c
> b/src/amd/vulkan/radv_cmd_buffer.c
> index a2d55833..4432afc 100644
> --- a/src/amd/vulkan/radv_cmd_buffer.c
> +++ b/src/amd/vulkan/radv_cmd_buffer.c
> @@ -2296,6 +2296,20 @@ static void radv_handle_dcc_image_transition(struct
> radv_cmd_buffer *cmd_buffer,
>         }
>  }
>
> +static void radv_handle_prime_image_transition(struct radv_cmd_buffer
> *cmd_buffer,
> +                                              struct radv_image *image,
> +                                              VkImageLayout src_layout,
> +                                              VkImageLayout dst_layout,
> +                                              VkImageSubresourceRange
> range,
> +                                              VkImageAspectFlags
> pending_clears)
> +{
> +       cmd_buffer->state.flush_bits |= RADV_CMD_FLUSH_AND_INV_FRAMEBUFFER;
> +       si_emit_cache_flush(cmd_buffer);
> +       radv_blit_to_prime_linear(cmd_buffer, image);
> +       cmd_buffer->state.flush_bits |= RADV_CMD_FLUSH_AND_INV_FRAMEBUFFER;
> +       si_emit_cache_flush(cmd_buffer);
> +}
> +
>  static void radv_handle_image_transition(struct radv_cmd_buffer
> *cmd_buffer,
>                                          struct radv_image *image,
>                                          VkImageLayout src_layout,
> @@ -2314,6 +2328,10 @@ static void radv_handle_image_transition(struct
> radv_cmd_buffer *cmd_buffer,
>         if (image->surface.dcc_size)
>                 radv_handle_dcc_image_transition(cmd_buffer, image,
> src_layout,
>                                                  dst_layout, range,
> pending_clears);
> +
> +       if (image->prime_image && dst_layout ==
> VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
> +               radv_handle_prime_image_transition(cmd_buffer, image,
> src_layout,
> +                                                  dst_layout, range,
> pending_clears);
>  }
>
>  void radv_CmdPipelineBarrier(
> diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c
> index c639d53..b21447f 100644
> --- a/src/amd/vulkan/radv_device.c
> +++ b/src/amd/vulkan/radv_device.c
> @@ -105,6 +105,9 @@ radv_physical_device_init(struct radv_physical_device
> *device,
>         }
>         drmFreeVersion(version);
>
> +       if (getenv("DRI_PRIME"))
> +               device->is_different_gpu = true;
> +
>         device->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
>         device->instance = instance;
>         assert(strlen(path) < ARRAY_SIZE(device->path));
> diff --git a/src/amd/vulkan/radv_meta.h b/src/amd/vulkan/radv_meta.h
> index 97d020c..e43a0e7 100644
> --- a/src/amd/vulkan/radv_meta.h
> +++ b/src/amd/vulkan/radv_meta.h
> @@ -186,6 +186,8 @@ void radv_meta_resolve_compute_image(struct
> radv_cmd_buffer *cmd_buffer,
>                                      uint32_t region_count,
>                                      const VkImageResolve *regions);
>
> +void radv_blit_to_prime_linear(struct radv_cmd_buffer *cmd_buffer,
> +                              struct radv_image *image);
>  #ifdef __cplusplus
>  }
>  #endif
> diff --git a/src/amd/vulkan/radv_meta_copy.c
> b/src/amd/vulkan/radv_meta_copy.c
> index 4c01eb7..3fd8d0c 100644
> --- a/src/amd/vulkan/radv_meta_copy.c
> +++ b/src/amd/vulkan/radv_meta_copy.c
> @@ -397,3 +397,34 @@ void radv_CmdCopyImage(
>
>         radv_meta_restore(&saved_state, cmd_buffer);
>  }
> +
> +void radv_blit_to_prime_linear(struct radv_cmd_buffer *cmd_buffer,
> +                              struct radv_image *image)
> +{
> +       struct radv_meta_saved_state saved_state;
> +       struct radv_meta_saved_pass_state saved_pass_state;
> +
> +       radv_meta_save_pass(&saved_pass_state, cmd_buffer);
> +       radv_meta_save_graphics_reset_vport_scissor(&saved_state,
> cmd_buffer);
> +
> +       struct radv_meta_blit2d_surf b_src =
> +               blit_surf_for_image_level_layer(image,
> +                                               VK_IMAGE_ASPECT_COLOR_BIT,
> +                                               0,
> +                                               0);
> +
> +       struct radv_meta_blit2d_surf b_dst =
> +               blit_surf_for_image_level_layer(image->prime_image,
> +                                               VK_IMAGE_ASPECT_COLOR_BIT,
> +                                               0,
> +                                               0);
> +       struct radv_meta_blit2d_rect rect = {
> +               .width = image->extent.width,
> +               .height = image->extent.height,
> +       };
> +
> +       radv_meta_blit2d(cmd_buffer, &b_src, NULL, &b_dst, 1, &rect);
> +
> +       radv_meta_restore(&saved_state, cmd_buffer);
> +       radv_meta_restore_pass(&saved_pass_state, cmd_buffer);
> +}
> diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h
> index e1c24cb..5027431 100644
> --- a/src/amd/vulkan/radv_private.h
> +++ b/src/amd/vulkan/radv_private.h
> @@ -261,6 +261,7 @@ struct radv_physical_device {
>         uint8_t                                     uuid[VK_UUID_SIZE];
>
>         struct wsi_device                       wsi_device;
> +       bool is_different_gpu;
>  };
>
>  struct radv_instance {
> @@ -987,6 +988,9 @@ struct radv_image {
>
>         /* Depth buffer compression and fast clear. */
>         struct r600_htile_info htile;
> +
> +       struct radv_image *prime_image;
> +       struct radv_device_memory *prime_memory;
>  };
>
>  bool radv_layout_has_htile(const struct radv_image *image,
> diff --git a/src/amd/vulkan/radv_wsi.c b/src/amd/vulkan/radv_wsi.c
> index 1f1ab1c..31aeb77 100644
> --- a/src/amd/vulkan/radv_wsi.c
> +++ b/src/amd/vulkan/radv_wsi.c
> @@ -135,23 +135,27 @@ VkResult
> radv_GetPhysicalDeviceSurfacePresentModesKHR(
>                                         pPresentModes);
>  }
>
> +static void
> +radv_wsi_image_destroy_single(VkDevice device_h,
> +                             const VkAllocationCallbacks* pAllocator,
> +                             VkImage image_h,
> +                             VkDeviceMemory memory_h)
> +{
> +       radv_DestroyImage(device_h, image_h, pAllocator);
> +       radv_FreeMemory(device_h, memory_h, pAllocator);
> +}
> +
>  static VkResult
> -radv_wsi_image_create(VkDevice device_h,
> -                     const VkSwapchainCreateInfoKHR *pCreateInfo,
> -                     const VkAllocationCallbacks* pAllocator,
> -                     VkImage *image_p,
> -                     VkDeviceMemory *memory_p,
> -                     uint32_t *size,
> -                     uint32_t *offset,
> -                     uint32_t *row_pitch, int *fd_p)
> +radv_wsi_image_create_single(VkDevice device_h,
> +                            const VkSwapchainCreateInfoKHR *pCreateInfo,
> +                            const VkAllocationCallbacks* pAllocator,
> +                            VkImage *image_p,
> +                            VkDeviceMemory *memory_p,
> +                            bool tiled)
>  {
> -       struct radv_device *device = radv_device_from_handle(device_h);
> -       VkResult result = VK_SUCCESS;
> -       struct radeon_surf *surface;
> +       VkResult result;
>         VkImage image_h;
>         struct radv_image *image;
> -       bool bret;
> -       int fd;
>
>         result = radv_image_create(device_h,
>                                    &(struct radv_image_create_info) {
> @@ -169,7 +173,7 @@ radv_wsi_image_create(VkDevice device_h,
>                                                    .arrayLayers = 1,
>                                                    .samples = 1,
>                                                    /* FIXME: Need a way to
> use X tiling to allow scanout */
> -                                                  .tiling =
> VK_IMAGE_TILING_OPTIMAL,
> +                                                  .tiling = tiled ?
> VK_IMAGE_TILING_OPTIMAL : VK_IMAGE_TILING_LINEAR,
>                                                    .usage =
> VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
>                                                    .flags = 0,
>                                            },
> @@ -180,24 +184,74 @@ radv_wsi_image_create(VkDevice device_h,
>                 return result;
>
>         image = radv_image_from_handle(image_h);
> -
>         VkDeviceMemory memory_h;
> -       struct radv_device_memory *memory;
> +
>         result = radv_AllocateMemory(device_h,
>                                      &(VkMemoryAllocateInfo) {
>                                              .sType =
> VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
>                                                      .allocationSize =
> image->size,
> -                                                    .memoryTypeIndex = 0,
> +                                                    .memoryTypeIndex =
> tiled ? 0 : 1,
>                                                      },
>                                      NULL /* XXX: pAllocator */,
>                                      &memory_h);
>         if (result != VK_SUCCESS)
>                 goto fail_create_image;
>
> -       memory = radv_device_memory_from_handle(memory_h);
> -
>         radv_BindImageMemory(VK_NULL_HANDLE, image_h, memory_h, 0);
>
> +       *image_p = image_h;
> +       *memory_p = memory_h;
> +       return VK_SUCCESS;
> +fail_create_image:
> +       radv_DestroyImage(device_h, image_h, pAllocator);
> +       return result;
> +}
> +
> +static VkResult
> +radv_wsi_image_create(VkDevice device_h,
> +                     const VkSwapchainCreateInfoKHR *pCreateInfo,
> +                     const VkAllocationCallbacks* pAllocator,
> +                     VkImage *image_p,
> +                     VkDeviceMemory *memory_p,
> +                     uint32_t *size,
> +                     uint32_t *offset,
> +                     uint32_t *row_pitch, int *fd_p)
> +{
> +       struct radv_device *device = radv_device_from_handle(device_h);
> +       VkResult result = VK_SUCCESS;
> +       struct radeon_surf *surface;
> +       VkImage image_h, image_prime_h;
> +       VkDeviceMemory memory_h, memory_prime_h;
> +       struct radv_image *image;
> +       struct radv_device_memory *memory;
> +       bool bret;
> +       int fd;
> +       bool prime = device->instance->physicalDevice.is_different_gpu;
> +
> +       result = radv_wsi_image_create_single(device_h, pCreateInfo,
> +                                             pAllocator, &image_h,
> &memory_h,
> +                                             true);
> +       if (result != VK_SUCCESS)
> +               return result;
> +
> +       image = radv_image_from_handle(image_h);
> +       if (prime) {
> +               result = radv_wsi_image_create_single(device_h,
> pCreateInfo,
> +                                                     pAllocator,
> &image_prime_h,
> +                                                     &memory_prime_h,
> false);
> +
> +               if (result != VK_SUCCESS)
> +                       goto fail_create_image;
> +
> +               image->prime_image = radv_image_from_handle(image_prime_h);
> +               image->prime_memory =
> radv_device_memory_from_handle(memory_prime_h);
> +
> +               memory = image->prime_memory;
> +               image = image->prime_image;
> +       } else {
> +               memory = radv_device_memory_from_handle(memory_h);
> +       }
> +
>         bret = device->ws->buffer_get_fd(device->ws,
>                                          memory->bo, &fd);
>         if (bret == false)
> @@ -217,24 +271,31 @@ radv_wsi_image_create(VkDevice device_h,
>         *offset = image->offset;
>         *row_pitch = surface->level[0].pitch_bytes;
>         return VK_SUCCESS;
> - fail_alloc_memory:
> -       radv_FreeMemory(device_h, memory_h, pAllocator);
> +
> +fail_alloc_memory:
> +       if (prime)
> +               radv_wsi_image_destroy_single(device_h, pAllocator,
> image_prime_h, memory_prime_h);
>
>  fail_create_image:
> -       radv_DestroyImage(device_h, image_h, pAllocator);
> +       radv_wsi_image_destroy_single(device_h, pAllocator, image_h,
> memory_h);
>
>         return result;
>  }
>
>  static void
> -radv_wsi_image_free(VkDevice device,
> +radv_wsi_image_free(VkDevice device_h,
>                     const VkAllocationCallbacks* pAllocator,
>                     VkImage image_h,
>                     VkDeviceMemory memory_h)
>  {
> -       radv_DestroyImage(device, image_h, pAllocator);
> +       RADV_FROM_HANDLE(radv_image, image, image_h);
> +
> +       if (image->prime_image)
> +               radv_wsi_image_destroy_single(device_h, pAllocator,
> +
>  radv_image_to_handle(image->prime_image),
> +
>  radv_device_memory_to_handle(image->prime_memory));
>
> -       radv_FreeMemory(device, memory_h, pAllocator);
> +       radv_wsi_image_destroy_single(device_h, pAllocator, image_h,
> memory_h);
>  }
>
>  static const struct wsi_image_fns radv_wsi_image_fns = {
> --
> 2.9.3
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20161123/8fb21c43/attachment-0001.html>


More information about the mesa-dev mailing list