mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-03 18:00:10 +01:00
vulkan/wsi: Implement GetPhysicalDevicePresentRectanglesKHR
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. Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
This commit is contained in:
parent
7629c00557
commit
7c65cf9844
8 changed files with 177 additions and 0 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue