[Mesa-dev] [PATCH 2/2] vulkan/wsi: Implement GetPhysicalDevicePresentRectanglesKHR

Lionel Landwerlin lionel.g.landwerlin at intel.com
Thu Oct 18 11:46:29 UTC 2018


Awesome!

Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin at intel.com>

On 17/10/2018 21:14, Jason Ekstrand wrote:
> This got missed during 1.1 enabling because it was defined as an
> interaction between device groups and WSI and it wasn't obvious it was
> in the delta.
>
> The idea behind it is that it's supposed to provide a hint to the
> application in a multi-GPU setup to indicate which regions of the screen
> are being scanned out by which GPU so a multi-device split-screen
> rendering application can render each part of the screen on the GPU that
> will be presenting it and avoid extra bus traffic between GPUs.  On a
> single-GPU setup or one which doesn't support this present mode, we need
> to do something.  We choose to return the window size (or a max-size
> rect) if the compositor, X server, or crtc is associated with the given
> physical device and zero rectangles otherwise.
> ---
>   src/amd/vulkan/radv_wsi.c           | 14 +++++++
>   src/intel/vulkan/anv_wsi.c          | 14 +++++++
>   src/vulkan/wsi/wsi_common.c         | 14 +++++++
>   src/vulkan/wsi/wsi_common.h         |  7 ++++
>   src/vulkan/wsi/wsi_common_display.c | 41 +++++++++++++++++++
>   src/vulkan/wsi/wsi_common_private.h |  5 +++
>   src/vulkan/wsi/wsi_common_wayland.c | 21 ++++++++++
>   src/vulkan/wsi/wsi_common_x11.c     | 61 +++++++++++++++++++++++++++++
>   8 files changed, 177 insertions(+)
>
> diff --git a/src/amd/vulkan/radv_wsi.c b/src/amd/vulkan/radv_wsi.c
> index 8b165ea3916..43103a4ef85 100644
> --- a/src/amd/vulkan/radv_wsi.c
> +++ b/src/amd/vulkan/radv_wsi.c
> @@ -284,3 +284,17 @@ VkResult radv_GetDeviceGroupSurfacePresentModesKHR(
>   
>      return VK_SUCCESS;
>   }
> +
> +VkResult radv_GetPhysicalDevicePresentRectanglesKHR(
> +	VkPhysicalDevice                            physicalDevice,
> +	VkSurfaceKHR                                surface,
> +	uint32_t*                                   pRectCount,
> +	VkRect2D*                                   pRects)
> +{
> +	RADV_FROM_HANDLE(radv_physical_device, device, physicalDevice);
> +
> +	return wsi_common_get_present_rectangles(&device->wsi_device,
> +						 device->local_fd,
> +						 surface,
> +						 pRectCount, pRects);
> +}
> diff --git a/src/intel/vulkan/anv_wsi.c b/src/intel/vulkan/anv_wsi.c
> index 1c9a54804e8..5d672c211c4 100644
> --- a/src/intel/vulkan/anv_wsi.c
> +++ b/src/intel/vulkan/anv_wsi.c
> @@ -293,3 +293,17 @@ VkResult anv_GetDeviceGroupSurfacePresentModesKHR(
>   
>      return VK_SUCCESS;
>   }
> +
> +VkResult anv_GetPhysicalDevicePresentRectanglesKHR(
> +    VkPhysicalDevice                            physicalDevice,
> +    VkSurfaceKHR                                surface,
> +    uint32_t*                                   pRectCount,
> +    VkRect2D*                                   pRects)
> +{
> +   ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
> +
> +   return wsi_common_get_present_rectangles(&device->wsi_device,
> +                                            device->local_fd,
> +                                            surface,
> +                                            pRectCount, pRects);
> +}
> diff --git a/src/vulkan/wsi/wsi_common.c b/src/vulkan/wsi/wsi_common.c
> index 1e3c4e0028b..ad4b8c9075e 100644
> --- a/src/vulkan/wsi/wsi_common.c
> +++ b/src/vulkan/wsi/wsi_common.c
> @@ -803,6 +803,20 @@ wsi_common_get_surface_present_modes(struct wsi_device *wsi_device,
>                                      pPresentModes);
>   }
>   
> +VkResult
> +wsi_common_get_present_rectangles(struct wsi_device *wsi_device,
> +                                  int local_fd,
> +                                  VkSurfaceKHR _surface,
> +                                  uint32_t* pRectCount,
> +                                  VkRect2D* pRects)
> +{
> +   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
> +   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
> +
> +   return iface->get_present_rectangles(surface, wsi_device, local_fd,
> +                                        pRectCount, pRects);
> +}
> +
>   VkResult
>   wsi_common_create_swapchain(struct wsi_device *wsi,
>                               VkDevice device,
> diff --git a/src/vulkan/wsi/wsi_common.h b/src/vulkan/wsi/wsi_common.h
> index 424330de566..5b69c573d9e 100644
> --- a/src/vulkan/wsi/wsi_common.h
> +++ b/src/vulkan/wsi/wsi_common.h
> @@ -199,6 +199,13 @@ wsi_common_get_surface_present_modes(struct wsi_device *wsi_device,
>                                        uint32_t *pPresentModeCount,
>                                        VkPresentModeKHR *pPresentModes);
>   
> +VkResult
> +wsi_common_get_present_rectangles(struct wsi_device *wsi,
> +                                  int local_fd,
> +                                  VkSurfaceKHR surface,
> +                                  uint32_t* pRectCount,
> +                                  VkRect2D* pRects);
> +
>   VkResult
>   wsi_common_get_surface_capabilities2ext(
>      struct wsi_device *wsi_device,
> diff --git a/src/vulkan/wsi/wsi_common_display.c b/src/vulkan/wsi/wsi_common_display.c
> index c004060a205..2315717ef8e 100644
> --- a/src/vulkan/wsi/wsi_common_display.c
> +++ b/src/vulkan/wsi/wsi_common_display.c
> @@ -934,6 +934,46 @@ wsi_display_surface_get_present_modes(VkIcdSurfaceBase *surface,
>      return vk_outarray_status(&conn);
>   }
>   
> +static bool
> +fds_are_same_gpu(int fd1, int fd2)
> +{
> +   if (fd1 == -1 || fd2 == -1)
> +      return false;
> +
> +   char *fd1_dev = drmGetRenderDeviceNameFromFd(fd1);
> +   char *fd2_dev = drmGetRenderDeviceNameFromFd(fd2);
> +
> +   int ret = strcmp(fd1_dev, fd2_dev);
> +
> +   free(fd1_dev);
> +   free(fd2_dev);
> +
> +   return ret == 0;
> +}
> +
> +static VkResult
> +wsi_display_surface_get_present_rectangles(VkIcdSurfaceBase *surface_base,
> +                                           struct wsi_device *wsi_device,
> +                                           int local_fd,
> +                                           uint32_t* pRectCount,
> +                                           VkRect2D* pRects)
> +{
> +   VkIcdSurfaceDisplay *surface = (VkIcdSurfaceDisplay *) surface_base;
> +   wsi_display_mode *mode = wsi_display_mode_from_handle(surface->displayMode);
> +   VK_OUTARRAY_MAKE(out, pRects, pRectCount);
> +
> +   if (fds_are_same_gpu(local_fd, mode->connector->wsi->fd)) {
> +      vk_outarray_append(&out, rect) {
> +         *rect = (VkRect2D) {
> +            .offset = { 0, 0 },
> +            .extent = { mode->hdisplay, mode->vdisplay },
> +         };
> +      }
> +   }
> +
> +   return vk_outarray_status(&out);
> +}
> +
>   static void
>   wsi_display_destroy_buffer(struct wsi_display *wsi,
>                              uint32_t buffer)
> @@ -1810,6 +1850,7 @@ wsi_display_init_wsi(struct wsi_device *wsi_device,
>      wsi->base.get_formats = wsi_display_surface_get_formats;
>      wsi->base.get_formats2 = wsi_display_surface_get_formats2;
>      wsi->base.get_present_modes = wsi_display_surface_get_present_modes;
> +   wsi->base.get_present_rectangles = wsi_display_surface_get_present_rectangles;
>      wsi->base.create_swapchain = wsi_display_surface_create_swapchain;
>   
>      wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY] = &wsi->base;
> diff --git a/src/vulkan/wsi/wsi_common_private.h b/src/vulkan/wsi/wsi_common_private.h
> index accc1170163..d8290b69331 100644
> --- a/src/vulkan/wsi/wsi_common_private.h
> +++ b/src/vulkan/wsi/wsi_common_private.h
> @@ -118,6 +118,11 @@ struct wsi_interface {
>      VkResult (*get_present_modes)(VkIcdSurfaceBase *surface,
>                                    uint32_t* pPresentModeCount,
>                                    VkPresentModeKHR* pPresentModes);
> +   VkResult (*get_present_rectangles)(VkIcdSurfaceBase *surface,
> +                                      struct wsi_device *wsi_device,
> +                                      int local_fd,
> +                                      uint32_t* pRectCount,
> +                                      VkRect2D* pRects);
>      VkResult (*create_swapchain)(VkIcdSurfaceBase *surface,
>                                   VkDevice device,
>                                   struct wsi_device *wsi_device,
> diff --git a/src/vulkan/wsi/wsi_common_wayland.c b/src/vulkan/wsi/wsi_common_wayland.c
> index 67d5f8d4c80..dccb530dae3 100644
> --- a/src/vulkan/wsi/wsi_common_wayland.c
> +++ b/src/vulkan/wsi/wsi_common_wayland.c
> @@ -601,6 +601,26 @@ wsi_wl_surface_get_present_modes(VkIcdSurfaceBase *surface,
>         return VK_SUCCESS;
>   }
>   
> +static VkResult
> +wsi_wl_surface_get_present_rectangles(VkIcdSurfaceBase *surface,
> +                                      struct wsi_device *wsi_device,
> +                                      int local_fd,
> +                                      uint32_t* pRectCount,
> +                                      VkRect2D* pRects)
> +{
> +   VK_OUTARRAY_MAKE(out, pRects, pRectCount);
> +
> +   vk_outarray_append(&out, rect) {
> +      /* We don't know a size so just return the usual "I don't know." */
> +      *rect = (VkRect2D) {
> +         .offset = { 0, 0 },
> +         .extent = { -1, -1 },
> +      };
> +   }
> +
> +   return vk_outarray_status(&out);
> +}
> +
>   VkResult wsi_create_wl_surface(const VkAllocationCallbacks *pAllocator,
>   			       const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
>   			       VkSurfaceKHR *pSurface)
> @@ -1012,6 +1032,7 @@ wsi_wl_init_wsi(struct wsi_device *wsi_device,
>      wsi->base.get_formats = wsi_wl_surface_get_formats;
>      wsi->base.get_formats2 = wsi_wl_surface_get_formats2;
>      wsi->base.get_present_modes = wsi_wl_surface_get_present_modes;
> +   wsi->base.get_present_rectangles = wsi_wl_surface_get_present_rectangles;
>      wsi->base.create_swapchain = wsi_wl_surface_create_swapchain;
>   
>      wsi_device->wsi[VK_ICD_WSI_PLATFORM_WAYLAND] = &wsi->base;
> diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c
> index 75aa83bb7b4..8c621ddf568 100644
> --- a/src/vulkan/wsi/wsi_common_x11.c
> +++ b/src/vulkan/wsi/wsi_common_x11.c
> @@ -599,6 +599,66 @@ x11_surface_get_present_modes(VkIcdSurfaceBase *surface,
>         VK_INCOMPLETE : VK_SUCCESS;
>   }
>   
> +static bool
> +x11_surface_is_local_to_gpu(struct wsi_device *wsi_dev,
> +                            int local_fd,
> +                            xcb_connection_t *conn)
> +{
> +   struct wsi_x11_connection *wsi_conn =
> +      wsi_x11_get_connection(wsi_dev, conn);
> +
> +   if (!wsi_conn)
> +      return false;
> +
> +   if (!wsi_x11_check_for_dri3(wsi_conn))
> +      return false;
> +
> +   if (!wsi_x11_check_dri3_compatible(conn, local_fd))
> +      return false;
> +
> +   return true;
> +}
> +
> +static VkResult
> +x11_surface_get_present_rectangles(VkIcdSurfaceBase *icd_surface,
> +                                   struct wsi_device *wsi_device,
> +                                   int local_fd,
> +                                   uint32_t* pRectCount,
> +                                   VkRect2D* pRects)
> +{
> +   xcb_connection_t *conn = x11_surface_get_connection(icd_surface);
> +   xcb_window_t window = x11_surface_get_window(icd_surface);
> +   VK_OUTARRAY_MAKE(out, pRects, pRectCount);
> +
> +   if (x11_surface_is_local_to_gpu(wsi_device, local_fd, conn)) {
> +      vk_outarray_append(&out, rect) {
> +         xcb_generic_error_t *err = NULL;
> +         xcb_get_geometry_cookie_t geom_cookie = xcb_get_geometry(conn, window);
> +         xcb_get_geometry_reply_t *geom =
> +            xcb_get_geometry_reply(conn, geom_cookie, &err);
> +         free(err);
> +         if (geom) {
> +            *rect = (VkRect2D) {
> +               .offset = { 0, 0 },
> +               .extent = { geom->width, geom->height },
> +            };
> +         } else {
> +            /* This can happen if the client didn't wait for the configure event
> +             * to come back from the compositor.  In that case, we don't know the
> +             * size of the window so we just return valid "I don't know" stuff.
> +             */
> +            *rect = (VkRect2D) {
> +               .offset = { 0, 0 },
> +               .extent = { -1, -1 },
> +            };
> +         }
> +         free(geom);
> +      }
> +   }
> +
> +   return vk_outarray_status(&out);
> +}
> +
>   VkResult wsi_create_xcb_surface(const VkAllocationCallbacks *pAllocator,
>   				const VkXcbSurfaceCreateInfoKHR *pCreateInfo,
>   				VkSurfaceKHR *pSurface)
> @@ -1470,6 +1530,7 @@ wsi_x11_init_wsi(struct wsi_device *wsi_device,
>      wsi->base.get_formats = x11_surface_get_formats;
>      wsi->base.get_formats2 = x11_surface_get_formats2;
>      wsi->base.get_present_modes = x11_surface_get_present_modes;
> +   wsi->base.get_present_rectangles = x11_surface_get_present_rectangles;
>      wsi->base.create_swapchain = x11_surface_create_swapchain;
>   
>      wsi_device->wsi[VK_ICD_WSI_PLATFORM_XCB] = &wsi->base;




More information about the mesa-dev mailing list