From 24db7caebdf26542a800c1ac0b089caa0a3f5a34 Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Wed, 7 Dec 2022 14:28:48 +0100 Subject: [PATCH] radv: import compiled binaries from libraries only when fast-linking is enabled When VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT is used, the pipeline includes a complete set of state specified entirely by libraries. That means that we should skip using compiled binaries (including PS epilogs) and we should create an optimized pipeline. Found this with Zink because RADV was creating two pipelines with the same PS epilog, while the optimized one shouldn't use any PS epilog. Signed-off-by: Samuel Pitoiset Reviewed-by: Bas Nieuwenhuizen Part-of: --- src/amd/vulkan/radv_pipeline.c | 61 +++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c index a9322fc0a25..2a37daf0fb9 100644 --- a/src/amd/vulkan/radv_pipeline.c +++ b/src/amd/vulkan/radv_pipeline.c @@ -1535,7 +1535,8 @@ static void radv_graphics_pipeline_import_lib(struct radv_graphics_pipeline *pipeline, struct vk_graphics_pipeline_state *state, struct radv_pipeline_layout *layout, - struct radv_graphics_lib_pipeline *lib) + struct radv_graphics_lib_pipeline *lib, + bool link_optimize) { /* There should be no common blocks between a lib we import and the current * pipeline we're building. @@ -1555,35 +1556,37 @@ radv_graphics_pipeline_import_lib(struct radv_graphics_pipeline *pipeline, pipeline->base.retained_shaders[s] = lib->base.base.retained_shaders[s]; } - /* Import the compiled shaders. */ - for (uint32_t s = 0; s < ARRAY_SIZE(lib->base.base.shaders); s++) { - if (!lib->base.base.shaders[s]) - continue; + if (!link_optimize) { + /* Import the compiled shaders. */ + for (uint32_t s = 0; s < ARRAY_SIZE(lib->base.base.shaders); s++) { + if (!lib->base.base.shaders[s]) + continue; - pipeline->base.shaders[s] = radv_shader_ref(lib->base.base.shaders[s]); + pipeline->base.shaders[s] = radv_shader_ref(lib->base.base.shaders[s]); - /* Hold a pointer to the slab BO to indicate the shader is already uploaded. */ - pipeline->base.shaders[s]->bo = lib->base.base.slab_bo; - } + /* Hold a pointer to the slab BO to indicate the shader is already uploaded. */ + pipeline->base.shaders[s]->bo = lib->base.base.slab_bo; + } - /* Import the GS copy shader if present. */ - if (lib->base.base.gs_copy_shader) { - assert(!pipeline->base.gs_copy_shader); - pipeline->base.gs_copy_shader = radv_shader_ref(lib->base.base.gs_copy_shader); + /* Import the GS copy shader if present. */ + if (lib->base.base.gs_copy_shader) { + assert(!pipeline->base.gs_copy_shader); + pipeline->base.gs_copy_shader = radv_shader_ref(lib->base.base.gs_copy_shader); - /* Hold a pointer to the slab BO to indicate the shader is already uploaded. */ - pipeline->base.gs_copy_shader->bo = lib->base.base.slab_bo; - } + /* Hold a pointer to the slab BO to indicate the shader is already uploaded. */ + pipeline->base.gs_copy_shader->bo = lib->base.base.slab_bo; + } - /* Refcount the slab BO to make sure it's not freed when the library is destroyed. */ - if (lib->base.base.slab) { - p_atomic_inc(&lib->base.base.slab->ref_count); - } + /* Refcount the slab BO to make sure it's not freed when the library is destroyed. */ + if (lib->base.base.slab) { + p_atomic_inc(&lib->base.base.slab->ref_count); + } - /* Import the PS epilog if present. */ - if (lib->base.ps_epilog) { - assert(!pipeline->ps_epilog); - pipeline->ps_epilog = radv_shader_part_ref(lib->base.ps_epilog); + /* Import the PS epilog if present. */ + if (lib->base.ps_epilog) { + assert(!pipeline->ps_epilog); + pipeline->ps_epilog = radv_shader_part_ref(lib->base.ps_epilog); + } } /* Import the pipeline layout. */ @@ -5387,7 +5390,7 @@ radv_graphics_pipeline_init(struct radv_graphics_pipeline *pipeline, struct radv /* If we have libraries, import them first. */ if (libs_info) { - ASSERTED const bool link_optimize = + const bool link_optimize = (pCreateInfo->flags & VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT) != 0; for (uint32_t i = 0; i < libs_info->libraryCount; i++) { @@ -5402,7 +5405,8 @@ radv_graphics_pipeline_init(struct radv_graphics_pipeline *pipeline, struct radv */ assert(!link_optimize || gfx_pipeline_lib->base.base.retain_shaders); - radv_graphics_pipeline_import_lib(pipeline, &state, &pipeline_layout, gfx_pipeline_lib); + radv_graphics_pipeline_import_lib(pipeline, &state, &pipeline_layout, gfx_pipeline_lib, + link_optimize); imported_flags |= gfx_pipeline_lib->lib_flags; } @@ -5588,13 +5592,16 @@ radv_graphics_lib_pipeline_init(struct radv_graphics_lib_pipeline *pipeline, /* If we have libraries, import them first. */ if (libs_info) { + const bool link_optimize = + (pCreateInfo->flags & VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT) != 0; + for (uint32_t i = 0; i < libs_info->libraryCount; i++) { RADV_FROM_HANDLE(radv_pipeline, pipeline_lib, libs_info->pLibraries[i]); struct radv_graphics_lib_pipeline *gfx_pipeline_lib = radv_pipeline_to_graphics_lib(pipeline_lib); radv_graphics_pipeline_import_lib(&pipeline->base, state, pipeline_layout, - gfx_pipeline_lib); + gfx_pipeline_lib, link_optimize); pipeline->lib_flags |= gfx_pipeline_lib->lib_flags;