radv: allow to build the main FS in a graphics pipeline library
Corner cases like implicit gl_PrimitiveID are currently broken and will be fixed later, but the general case should work. Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com> Reviewed-by: Timur Kristóf <timur.kristof@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18516>
This commit is contained in:

committed by
Marge Bot

parent
e529745be3
commit
0f88f57223
@@ -227,6 +227,11 @@ radv_pipeline_destroy(struct radv_device *device, struct radv_pipeline *pipeline
|
||||
radv_pipeline_layout_finish(device, &gfx_pipeline_lib->layout);
|
||||
|
||||
for (unsigned i = 0; i < MESA_VULKAN_SHADER_STAGES; ++i) {
|
||||
if (pipeline->shaders[i]) {
|
||||
free(pipeline->shaders[i]->binary);
|
||||
pipeline->shaders[i]->binary = NULL;
|
||||
}
|
||||
|
||||
ralloc_free(pipeline->retained_shaders[i].nir);
|
||||
}
|
||||
|
||||
@@ -1602,6 +1607,14 @@ 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;
|
||||
|
||||
pipeline->base.shaders[s] = radv_shader_ref(lib->base.base.shaders[s]);
|
||||
}
|
||||
|
||||
/* Import the PS epilog if present. */
|
||||
if (lib->base.ps_epilog) {
|
||||
assert(!pipeline->ps_epilog);
|
||||
@@ -3643,6 +3656,10 @@ radv_pipeline_get_nir(struct radv_pipeline *pipeline, struct radv_pipeline_stage
|
||||
if (!stages[s].entrypoint)
|
||||
continue;
|
||||
|
||||
/* Do not try to get the NIR when we already have the assembly. */
|
||||
if (pipeline->shaders[s])
|
||||
continue;
|
||||
|
||||
int64_t stage_start = os_time_get_nano();
|
||||
|
||||
assert(retain_shaders || pipeline->shaders[s] == NULL);
|
||||
@@ -3850,6 +3867,29 @@ radv_postprocess_nir(struct radv_pipeline *pipeline,
|
||||
NIR_PASS(_, stage->nir, nir_opt_move, move_opts);
|
||||
}
|
||||
|
||||
static bool
|
||||
radv_pipeline_create_ps_epilog(struct radv_graphics_pipeline *pipeline,
|
||||
const struct radv_pipeline_key *pipeline_key)
|
||||
{
|
||||
struct radv_device *device = pipeline->base.device;
|
||||
|
||||
if (pipeline->base.shaders[MESA_SHADER_FRAGMENT] &&
|
||||
pipeline->base.shaders[MESA_SHADER_FRAGMENT]->info.ps.has_epilog && !pipeline->ps_epilog) {
|
||||
struct radv_ps_epilog_key epilog_key = {
|
||||
.spi_shader_col_format = pipeline_key->ps.col_format,
|
||||
.color_is_int8 = pipeline_key->ps.is_int8,
|
||||
.color_is_int10 = pipeline_key->ps.is_int10,
|
||||
.enable_mrt_output_nan_fixup = pipeline_key->ps.enable_mrt_output_nan_fixup,
|
||||
};
|
||||
|
||||
pipeline->ps_epilog = radv_create_ps_epilog(device, &epilog_key);
|
||||
if (!pipeline->ps_epilog)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
VkResult
|
||||
radv_create_shaders(struct radv_pipeline *pipeline, struct radv_pipeline_layout *pipeline_layout,
|
||||
struct radv_device *device, struct radv_pipeline_cache *cache,
|
||||
@@ -4054,6 +4094,14 @@ radv_create_shaders(struct radv_pipeline *pipeline, struct radv_pipeline_layout
|
||||
}
|
||||
}
|
||||
|
||||
/* When the main FS is compiled inside a library, we need to compile a PS epilog if it hasn't
|
||||
* been already imported.
|
||||
*/
|
||||
if (pipeline->type == RADV_PIPELINE_GRAPHICS) {
|
||||
if (!radv_pipeline_create_ps_epilog(radv_pipeline_to_graphics(pipeline), pipeline_key))
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Upload shader binaries. */
|
||||
radv_upload_shaders(device, pipeline);
|
||||
|
||||
@@ -4079,7 +4127,7 @@ radv_create_shaders(struct radv_pipeline *pipeline, struct radv_pipeline_layout
|
||||
}
|
||||
|
||||
for (int i = 0; i < MESA_VULKAN_SHADER_STAGES; ++i) {
|
||||
if (pipeline->shaders[i]) {
|
||||
if (pipeline->shaders[i] && !(flags & VK_PIPELINE_CREATE_LIBRARY_BIT_KHR)) {
|
||||
free(pipeline->shaders[i]->binary);
|
||||
pipeline->shaders[i]->binary = NULL;
|
||||
}
|
||||
@@ -6254,12 +6302,24 @@ radv_graphics_lib_pipeline_init(struct radv_graphics_lib_pipeline *pipeline,
|
||||
struct radv_pipeline_key key =
|
||||
radv_generate_graphics_pipeline_key(&pipeline->base, pCreateInfo, state, &blend);
|
||||
|
||||
/* FIXME: Force the driver to always retain the NIR shaders (after SPIRV->NIR) because it
|
||||
* doesn't yet support VS prologs and PS epilogs. This is very suboptimal, slow but for good
|
||||
* enough for a start.
|
||||
/* Compile the main FS only when the fragment shader output interface is missing. */
|
||||
if ((imported_flags & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) &&
|
||||
!(imported_flags & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT)) {
|
||||
key.ps.has_epilog = true;
|
||||
}
|
||||
|
||||
/* FIXME: Force the driver to retain the NIR shaders (after SPIRV->NIR) because it doesn't yet
|
||||
* support pre-rasterization stages. This is very suboptimal, slow but good enough for a
|
||||
* start.
|
||||
*/
|
||||
VkPipelineCreateFlags flags =
|
||||
pCreateInfo->flags | VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT;
|
||||
VkPipelineCreateFlags flags = pCreateInfo->flags;
|
||||
if (pipeline->base.active_stages & (VK_SHADER_STAGE_VERTEX_BIT |
|
||||
VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
|
||||
VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT |
|
||||
VK_SHADER_STAGE_GEOMETRY_BIT |
|
||||
VK_SHADER_STAGE_MESH_BIT_NV)) {
|
||||
flags |= VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT;
|
||||
}
|
||||
|
||||
result = radv_create_shaders(&pipeline->base.base, pipeline_layout, device, cache, &key,
|
||||
pCreateInfo->pStages, pCreateInfo->stageCount, flags, NULL,
|
||||
|
Reference in New Issue
Block a user