[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