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

Mike Lothian mike at fireburn.co.uk
Wed Nov 23 18:35:03 UTC 2016


It works with the Talos Principle and performs well, I'm seeing some
artefacts in the grass which can be seen in https://imgur.com/a/3litB I'm
not sure if that's caused by one of the LLVM bugs that have been mentioned

On Wed, 23 Nov 2016 at 11:13 Mike Lothian <mike at fireburn.co.uk> wrote:

> I think it would be good to keep the DRI_PRIME switch to allow for
> switching between anvil and radv, handy for testing / comparing /
> benchmarking both
>
> It seems that Vulkan automatically uses the first card listed in
> vulkaninfo (in my case it's the amdgpu card) with no way to select which is
> used, hence why I've only been seeing garbage since the radv driver was
> added into mesa
>
> If DRI_PRIME=0 is passed will this now automatically use anvil?
>
> Thanks
>
> Mike
>
> On Wed, 23 Nov 2016 at 10:47 Nicolai Hähnle <nhaehnle at gmail.com> wrote:
>
> On 23.11.2016 06:28, Dave Airlie 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.
>
> Why is there a problem here? What stops you from just having multiple
> SDMA queues?
>
>
> > 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.
>
> So I'm not too deep into Vulkan, but isn't conceptually the blit to
> shadow image a part of the present operation, not of the image
> transition? I'd somehow expect the present part to have its own queue
> (which could be SDMA) on which the blit happens.
>
> Cheers,
> Nicolai
>
> >
> > 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 = {
> >
> _______________________________________________
> 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/c0ab03e2/attachment-0001.html>


More information about the mesa-dev mailing list