From e63acdd2b7b1ef80e09545cfdfa5fea5d42d6159 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Fri, 21 Feb 2025 14:01:48 -0500 Subject: [PATCH] zink: force cached mem for streaming uploads it was previously possible to hit a path where an idle buffer with non-cached mem could be directly mapped for streaming data uploads, which kills perf Part-of: --- src/gallium/drivers/zink/zink_resource.c | 13 +++++++------ src/gallium/drivers/zink/zink_screen.c | 2 ++ src/gallium/drivers/zink/zink_types.h | 1 + 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/gallium/drivers/zink/zink_resource.c b/src/gallium/drivers/zink/zink_resource.c index 0ab68d61706..f1d6076045c 100644 --- a/src/gallium/drivers/zink/zink_resource.c +++ b/src/gallium/drivers/zink/zink_resource.c @@ -2340,14 +2340,17 @@ zink_buffer_map(struct pipe_context *pctx, } unsigned map_offset = box->x; + /* ideally never ever read or write to non-cached mem */ + bool is_cached_mem = (screen->info.mem_props.memoryTypes[res->obj->bo->base.base.placement].propertyFlags & VK_STAGING_RAM) == VK_STAGING_RAM; + /* but this is only viable with a certain amount of vram since it may fully duplicate lots of large buffers */ + bool host_mem_type_check = screen->always_cached_upload ? is_cached_mem : res->obj->host_visible; if (usage & PIPE_MAP_DISCARD_RANGE && - (!res->obj->host_visible || - !(usage & (PIPE_MAP_UNSYNCHRONIZED | PIPE_MAP_PERSISTENT)))) { + (!host_mem_type_check || !(usage & (PIPE_MAP_UNSYNCHRONIZED | PIPE_MAP_PERSISTENT)))) { /* Check if mapping this buffer would cause waiting for the GPU. */ - if (!res->obj->host_visible || force_discard_range || + if (!host_mem_type_check || force_discard_range || !zink_resource_usage_check_completion(screen, res, ZINK_RESOURCE_ACCESS_RW)) { /* Do a wait-free write-only transfer using a temporary buffer. */ unsigned offset; @@ -2381,9 +2384,7 @@ zink_buffer_map(struct pipe_context *pctx, if (!zink_resource_usage_check_completion(screen, res, ZINK_RESOURCE_ACCESS_WRITE)) goto success; usage |= PIPE_MAP_UNSYNCHRONIZED; - } else if (((usage & PIPE_MAP_READ) && !(usage & PIPE_MAP_PERSISTENT) && - ((screen->info.mem_props.memoryTypes[res->obj->bo->base.base.placement].propertyFlags & VK_STAGING_RAM) != VK_STAGING_RAM)) || - !res->obj->host_visible) { + } else if ((usage & PIPE_MAP_READ) && !(usage & PIPE_MAP_PERSISTENT) && !host_mem_type_check) { /* any read, non-HV write, or unmappable that reaches this point needs staging */ if ((usage & PIPE_MAP_READ) || !res->obj->host_visible || res->base.b.flags & PIPE_RESOURCE_FLAG_DONT_MAP_DIRECTLY) { overwrite: diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c index b3f37e8c747..4dea885833d 100644 --- a/src/gallium/drivers/zink/zink_screen.c +++ b/src/gallium/drivers/zink/zink_screen.c @@ -3365,6 +3365,8 @@ zink_internal_create_screen(const struct pipe_screen_config *config, int64_t dev /* determine if vis vram is roughly equal to total vram */ if (biggest_vis_vram > biggest_vram * 0.9) screen->resizable_bar = true; + if (biggest_vis_vram >= 8ULL * 1024ULL * 1024ULL * 1024ULL) + screen->always_cached_upload = true; } setup_renderdoc(screen); diff --git a/src/gallium/drivers/zink/zink_types.h b/src/gallium/drivers/zink/zink_types.h index 16718e20a5c..126657f4f19 100644 --- a/src/gallium/drivers/zink/zink_types.h +++ b/src/gallium/drivers/zink/zink_types.h @@ -1456,6 +1456,7 @@ struct zink_screen { uint8_t heap_map[ZINK_HEAP_MAX][VK_MAX_MEMORY_TYPES]; // mapping from zink heaps to memory type indices uint8_t heap_count[ZINK_HEAP_MAX]; // number of memory types per zink heap bool resizable_bar; + bool always_cached_upload; uint64_t total_video_mem; uint64_t clamp_video_mem;