mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-06-06 23:38:25 +02:00
zink: add renderonly scanouts handling
Add support for allocating scanouts via renderonly, to allow Zink usage with render-only GPUs paired with display-only scanout device. Signed-off-by: Frank Binns <frank.binns@imgtec.com> [Icenowy: split patch, forward port, require modifiers] Signed-off-by: Icenowy Zheng <uwu@icenowy.me> Signed-off-by: Icenowy Zheng <zhengxingda@iscas.ac.cn> Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com> Reviewed-By: Daniel Stone <daniels@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38810>
This commit is contained in:
parent
74b8fb330e
commit
83e92f2b5f
5 changed files with 138 additions and 11 deletions
|
|
@ -421,7 +421,7 @@ static struct pipe_screen *
|
|||
pipe_zink_create_screen(int fd, const struct pipe_screen_config *config)
|
||||
{
|
||||
struct pipe_screen *screen;
|
||||
screen = zink_drm_create_screen(fd, config);
|
||||
screen = zink_drm_create_screen(fd, config, NULL);
|
||||
return screen ? debug_screen_wrap(screen) : NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#define ZINK_PUBLIC_H
|
||||
|
||||
struct pipe_screen;
|
||||
struct renderonly;
|
||||
struct sw_winsys;
|
||||
struct pipe_screen_config;
|
||||
|
||||
|
|
@ -32,7 +33,7 @@ struct pipe_screen *
|
|||
zink_create_screen(struct sw_winsys *winsys, const struct pipe_screen_config *config);
|
||||
|
||||
struct pipe_screen *
|
||||
zink_drm_create_screen(int fd, const struct pipe_screen_config *config);
|
||||
zink_drm_create_screen(int fd, const struct pipe_screen_config *config, struct renderonly *ro);
|
||||
struct pipe_screen *
|
||||
zink_win32_create_screen(uint64_t adapter_luid);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -255,6 +255,12 @@ zink_resource_destroy(struct pipe_screen *pscreen,
|
|||
struct zink_resource *res = zink_resource(pres);
|
||||
/* prevent double-free when unrefing internal surfaces */
|
||||
res->base.b.reference.count = 999;
|
||||
|
||||
#ifdef HAVE_LIBDRM
|
||||
if (res->ro_scanout)
|
||||
renderonly_scanout_destroy(res->ro_scanout, screen->ro);
|
||||
#endif
|
||||
|
||||
if (pres->target == PIPE_BUFFER) {
|
||||
util_range_destroy(&res->valid_buffer_range);
|
||||
util_idalloc_mt_free(&screen->buffer_ids, res->base.buffer_id_unique);
|
||||
|
|
@ -1610,8 +1616,52 @@ resource_create(struct pipe_screen *pscreen,
|
|||
if (templ2.flags & PIPE_RESOURCE_FLAG_SPARSE &&
|
||||
(util_res_sample_count(templ) == 1 || screen->info.feats.features.shaderStorageImageMultisample))
|
||||
templ2.bind |= PIPE_BIND_SHADER_IMAGE;
|
||||
|
||||
#ifdef HAVE_LIBDRM
|
||||
if (!whandle && screen->ro && (templ2.bind & PIPE_BIND_SCANOUT)) {
|
||||
struct winsys_handle handle;
|
||||
|
||||
assert(screen->info.have_EXT_image_drm_format_modifier);
|
||||
|
||||
/* Only LINEAR is considered the appropriate modifier for scaning out
|
||||
* now, so sort out it if it's present, and fail if a modifier list is
|
||||
* present but does not include LINEAR.
|
||||
*/
|
||||
for (int i = 0; i < modifiers_count; i++) {
|
||||
if (res->modifiers[i] == DRM_FORMAT_MOD_LINEAR) {
|
||||
res->modifiers[0] = DRM_FORMAT_MOD_LINEAR;
|
||||
res->modifiers_count = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (modifiers_count > 0 && res->modifiers[0] != DRM_FORMAT_MOD_LINEAR) {
|
||||
/* Failed to find LINEAR in the modifier list */
|
||||
free(res->modifiers);
|
||||
FREE_CL(res);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res->ro_scanout =
|
||||
renderonly_scanout_for_resource(&templ2, screen->ro, &handle);
|
||||
|
||||
if (!res->ro_scanout) {
|
||||
free(res->modifiers);
|
||||
FREE_CL(res);
|
||||
return NULL;
|
||||
}
|
||||
assert(handle.type == WINSYS_HANDLE_TYPE_FD);
|
||||
assert(handle.modifier == DRM_FORMAT_MOD_LINEAR);
|
||||
whandle = &handle;
|
||||
}
|
||||
#endif
|
||||
|
||||
res->obj = resource_object_create(screen, &templ2, whandle, &linear, res->modifiers, res->modifiers_count, loader_private, user_mem);
|
||||
if (!res->obj) {
|
||||
#ifdef HAVE_LIBDRM
|
||||
if (res->ro_scanout)
|
||||
renderonly_scanout_destroy(res->ro_scanout, screen->ro);
|
||||
#endif
|
||||
free(res->modifiers);
|
||||
FREE_CL(res);
|
||||
return NULL;
|
||||
|
|
@ -1852,6 +1902,12 @@ zink_resource_get_param(struct pipe_screen *pscreen, struct pipe_context *pctx,
|
|||
break;
|
||||
|
||||
case PIPE_RESOURCE_PARAM_STRIDE: {
|
||||
#ifdef HAVE_LIBDRM
|
||||
if (res->ro_scanout) {
|
||||
*value = res->ro_scanout->stride;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
VkImageSubresource sub_res = {0};
|
||||
VkSubresourceLayout sub_res_layout = {0};
|
||||
|
||||
|
|
@ -1864,6 +1920,12 @@ zink_resource_get_param(struct pipe_screen *pscreen, struct pipe_context *pctx,
|
|||
}
|
||||
|
||||
case PIPE_RESOURCE_PARAM_OFFSET: {
|
||||
#ifdef HAVE_LIBDRM
|
||||
if (res->ro_scanout) {
|
||||
*value = 0;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
VkImageSubresource isr = {
|
||||
aspect,
|
||||
level,
|
||||
|
|
@ -1941,6 +2003,10 @@ zink_resource_get_handle(struct pipe_screen *pscreen,
|
|||
{
|
||||
if (tex->target == PIPE_BUFFER)
|
||||
tc_buffer_disable_cpu_storage(tex);
|
||||
#ifdef HAVE_LIBDRM
|
||||
if (whandle->type == WINSYS_HANDLE_TYPE_KMS && zink_screen(pscreen)->ro)
|
||||
return renderonly_get_handle(zink_resource(tex)->ro_scanout, whandle);
|
||||
#endif
|
||||
if (whandle->type == WINSYS_HANDLE_TYPE_FD || whandle->type == WINSYS_HANDLE_TYPE_KMS) {
|
||||
#ifdef ZINK_USE_DMABUF
|
||||
while (whandle->plane && tex->next && !zink_resource_is_aux_plane(tex->next)) {
|
||||
|
|
@ -2036,8 +2102,10 @@ zink_resource_from_handle(struct pipe_screen *pscreen,
|
|||
unsigned usage)
|
||||
{
|
||||
#ifdef ZINK_USE_DMABUF
|
||||
struct zink_screen *screen = zink_screen(pscreen);
|
||||
|
||||
if (whandle->modifier != DRM_FORMAT_MOD_INVALID &&
|
||||
!zink_screen(pscreen)->info.have_EXT_image_drm_format_modifier)
|
||||
!screen->info.have_EXT_image_drm_format_modifier)
|
||||
return NULL;
|
||||
|
||||
struct pipe_resource templ2 = *templ;
|
||||
|
|
@ -2070,6 +2138,19 @@ zink_resource_from_handle(struct pipe_screen *pscreen,
|
|||
res->obj->immutable_handle = true;
|
||||
res->internal_format = whandle->format;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBDRM
|
||||
if (screen->ro) {
|
||||
struct zink_resource *res = zink_resource(pres);
|
||||
|
||||
/* Make sure that renderonly has a handle to our buffer in the display's
|
||||
* fd, so that a later renderonly_get_handle() returns correct handles
|
||||
* or GEM names.
|
||||
*/
|
||||
res->ro_scanout = renderonly_create_gpu_import_for_resource(pres, screen->ro, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
return pres;
|
||||
#else
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -169,6 +169,14 @@ zink_get_device_vendor(struct pipe_screen *pscreen)
|
|||
return zink_screen(pscreen)->vendor_name;
|
||||
}
|
||||
|
||||
static int
|
||||
zink_get_screen_fd(struct pipe_screen *pscreen)
|
||||
{
|
||||
struct zink_screen *screen = zink_screen(pscreen);
|
||||
|
||||
return screen->drm_fd;
|
||||
}
|
||||
|
||||
static const char *
|
||||
zink_get_name(struct pipe_screen *pscreen)
|
||||
{
|
||||
|
|
@ -1662,6 +1670,11 @@ zink_destroy_screen(struct pipe_screen *pscreen)
|
|||
if (screen->loader_lib)
|
||||
util_dl_close(screen->loader_lib);
|
||||
|
||||
#ifdef HAVE_LIBDRM
|
||||
if (screen->ro)
|
||||
screen->ro->destroy(screen->ro);
|
||||
#endif
|
||||
|
||||
if (screen->drm_fd != -1)
|
||||
close(screen->drm_fd);
|
||||
|
||||
|
|
@ -3613,6 +3626,7 @@ zink_internal_create_screen(const struct pipe_screen_config *config, int64_t dev
|
|||
for (unsigned i = 0; i < ARRAY_SIZE(screen->base.nir_options); i++)
|
||||
screen->base.nir_options[i] = &screen->nir_options;
|
||||
|
||||
screen->base.get_screen_fd = zink_get_screen_fd;
|
||||
screen->base.get_name = zink_get_name;
|
||||
if (screen->instance_info->have_KHR_external_memory_capabilities) {
|
||||
screen->base.get_device_uuid = zink_get_device_uuid;
|
||||
|
|
@ -3869,25 +3883,44 @@ free_device:
|
|||
}
|
||||
|
||||
struct pipe_screen *
|
||||
zink_drm_create_screen(int fd, const struct pipe_screen_config *config)
|
||||
zink_drm_create_screen(int fd, const struct pipe_screen_config *config, struct renderonly *ro)
|
||||
{
|
||||
int64_t dev_major, dev_minor;
|
||||
struct zink_screen *ret;
|
||||
struct zink_screen *ret = NULL;
|
||||
|
||||
if (zink_render_rdev(fd, &dev_major, &dev_minor))
|
||||
return NULL;
|
||||
|
||||
ret = zink_internal_create_screen(config, dev_major, dev_minor, 0);
|
||||
|
||||
if (ret)
|
||||
ret->drm_fd = os_dupfd_cloexec(fd);
|
||||
if (ret && !ret->info.have_KHR_external_memory_fd) {
|
||||
debug_printf("ZINK: KHR_external_memory_fd required!\n");
|
||||
zink_destroy_screen(&ret->base);
|
||||
if (!ret)
|
||||
return NULL;
|
||||
|
||||
ret->drm_fd = os_dupfd_cloexec(fd);
|
||||
#ifdef HAVE_LIBDRM
|
||||
ret->ro = ro;
|
||||
#else
|
||||
assert(!ro);
|
||||
#endif
|
||||
|
||||
if (!ret->info.have_KHR_external_memory_fd) {
|
||||
debug_printf("ZINK: KHR_external_memory_fd required!\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Renderonly device may allocate buffers with arbitrary stride that
|
||||
* can only be supported with EXT_image_drm_format_modifier.
|
||||
*/
|
||||
if (ro && !ret->info.have_EXT_image_drm_format_modifier) {
|
||||
debug_printf("ZINK: EXT_image_drm_format_modifier required for renderonly GPUs!\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return &ret->base;
|
||||
|
||||
fail:
|
||||
zink_destroy_screen(&ret->base);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct pipe_screen *
|
||||
|
|
|
|||
|
|
@ -40,6 +40,11 @@
|
|||
#include "util/pb_slab.h"
|
||||
|
||||
#include "util/blob.h"
|
||||
|
||||
#ifdef HAVE_LIBDRM
|
||||
#include "renderonly/renderonly.h"
|
||||
#endif
|
||||
|
||||
#include "util/disk_cache.h"
|
||||
#include "util/hash_table.h"
|
||||
#include "util/list.h"
|
||||
|
|
@ -1323,6 +1328,10 @@ struct zink_resource {
|
|||
|
||||
uint8_t modifiers_count;
|
||||
uint64_t *modifiers;
|
||||
|
||||
#ifdef HAVE_LIBDRM
|
||||
struct renderonly_scanout *ro_scanout;
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline struct zink_resource *
|
||||
|
|
@ -1398,6 +1407,9 @@ struct zink_screen {
|
|||
|
||||
bool device_lost;
|
||||
int drm_fd;
|
||||
#ifdef HAVE_LIBDRM
|
||||
struct renderonly *ro;
|
||||
#endif
|
||||
|
||||
struct slab_parent_pool transfer_pool;
|
||||
struct disk_cache *disk_cache;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue