panvk: use static noperspective when statically linking VS and FS

This triggers with VK_EXT_graphics_pipeline_library and monolithic
pipelines when VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT is set.
With VK_EXT_shader_object, it would trigger when
VK_SHADER_CREATE_LINK_STAGE_BIT_EXT is set on both VS and FS.

The fast-linking interface from [1] (unmerged) would allow us to use the
optimization with monolithic pipelines.

[1]: https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27024/diffs?commit_id=cd1ba4d6375764680c5ced9be90f5519b92eefe6

Signed-off-by: Benjamin Lee <benjamin.lee@collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32127>
This commit is contained in:
Benjamin Lee 2024-11-15 20:58:37 -08:00 committed by Marge Bot
parent 98de4f42ff
commit d93f9d6d1a
3 changed files with 34 additions and 8 deletions

View file

@ -183,8 +183,8 @@ collect_noperspective_varyings_fs(UNUSED nir_builder *b,
return false; return false;
} }
static uint32_t uint32_t
nir_collect_noperspective_varyings_fs(nir_shader *s) pan_nir_collect_noperspective_varyings_fs(nir_shader *s)
{ {
assert(s->info.stage == MESA_SHADER_FRAGMENT); assert(s->info.stage == MESA_SHADER_FRAGMENT);
@ -233,5 +233,6 @@ pan_nir_collect_varyings(nir_shader *s, struct pan_shader_info *info)
info->varyings.input_count = count; info->varyings.input_count = count;
if (s->info.stage == MESA_SHADER_FRAGMENT) if (s->info.stage == MESA_SHADER_FRAGMENT)
info->varyings.noperspective = nir_collect_noperspective_varyings_fs(s); info->varyings.noperspective =
pan_nir_collect_noperspective_varyings_fs(s);
} }

View file

@ -401,6 +401,7 @@ bool pan_lower_xfb(nir_shader *nir);
bool pan_lower_image_index(nir_shader *shader, unsigned vs_img_attrib_offset); bool pan_lower_image_index(nir_shader *shader, unsigned vs_img_attrib_offset);
uint32_t pan_nir_collect_noperspective_varyings_fs(nir_shader *s);
void pan_nir_collect_varyings(nir_shader *s, struct pan_shader_info *info); void pan_nir_collect_varyings(nir_shader *s, struct pan_shader_info *info);
/* /*

View file

@ -121,7 +121,6 @@ panvk_lower_sysvals(nir_builder *b, nir_instr *instr, void *data)
bit_size, num_comps); bit_size, num_comps);
break; break;
case nir_intrinsic_load_noperspective_varyings_pan: case nir_intrinsic_load_noperspective_varyings_pan:
/* TODO: lower this to a constant with monolithic pipelines */
/* TODO: use a VS epilog specialized on constant noperspective_varyings /* TODO: use a VS epilog specialized on constant noperspective_varyings
* with VK_EXT_graphics_pipeline_libraries and VK_EXT_shader_object */ * with VK_EXT_graphics_pipeline_libraries and VK_EXT_shader_object */
assert(b->shader->info.stage == MESA_SHADER_VERTEX); assert(b->shader->info.stage == MESA_SHADER_VERTEX);
@ -495,6 +494,7 @@ panvk_lower_nir(struct panvk_device *dev, nir_shader *nir,
uint32_t set_layout_count, uint32_t set_layout_count,
struct vk_descriptor_set_layout *const *set_layouts, struct vk_descriptor_set_layout *const *set_layouts,
const struct vk_pipeline_robustness_state *rs, const struct vk_pipeline_robustness_state *rs,
uint32_t *noperspective_varyings,
const struct panfrost_compile_inputs *compile_input, const struct panfrost_compile_inputs *compile_input,
struct panvk_shader *shader) struct panvk_shader *shader)
{ {
@ -606,6 +606,10 @@ panvk_lower_nir(struct panvk_device *dev, nir_shader *nir,
if (PAN_ARCH < 9 && stage == MESA_SHADER_VERTEX) if (PAN_ARCH < 9 && stage == MESA_SHADER_VERTEX)
NIR_PASS(_, nir, pan_lower_image_index, MAX_VS_ATTRIBS); NIR_PASS(_, nir, pan_lower_image_index, MAX_VS_ATTRIBS);
if (noperspective_varyings && stage == MESA_SHADER_VERTEX)
NIR_PASS(_, nir, pan_nir_lower_static_noperspective,
*noperspective_varyings);
NIR_PASS(_, nir, nir_shader_instructions_pass, panvk_lower_sysvals, NIR_PASS(_, nir, nir_shader_instructions_pass, panvk_lower_sysvals,
nir_metadata_control_flow, NULL); nir_metadata_control_flow, NULL);
} }
@ -880,6 +884,7 @@ static VkResult
panvk_compile_shader(struct panvk_device *dev, panvk_compile_shader(struct panvk_device *dev,
struct vk_shader_compile_info *info, struct vk_shader_compile_info *info,
const struct vk_graphics_pipeline_state *state, const struct vk_graphics_pipeline_state *state,
uint32_t *noperspective_varyings,
const VkAllocationCallbacks *pAllocator, const VkAllocationCallbacks *pAllocator,
struct vk_shader **shader_out) struct vk_shader **shader_out)
{ {
@ -908,7 +913,7 @@ panvk_compile_shader(struct panvk_device *dev,
nir->info.fs.uses_sample_shading = true; nir->info.fs.uses_sample_shading = true;
panvk_lower_nir(dev, nir, info->set_layout_count, info->set_layouts, panvk_lower_nir(dev, nir, info->set_layout_count, info->set_layouts,
info->robustness, &inputs, shader); info->robustness, noperspective_varyings, &inputs, shader);
result = panvk_compile_nir(dev, nir, info->flags, &inputs, shader); result = panvk_compile_nir(dev, nir, info->flags, &inputs, shader);
@ -937,11 +942,20 @@ panvk_compile_shaders(struct vk_device *vk_dev, uint32_t shader_count,
struct vk_shader **shaders_out) struct vk_shader **shaders_out)
{ {
struct panvk_device *dev = to_panvk_device(vk_dev); struct panvk_device *dev = to_panvk_device(vk_dev);
bool use_static_noperspective = false;
uint32_t noperspective_varyings = 0;
VkResult result; VkResult result;
uint32_t i; int32_t i;
for (i = 0; i < shader_count; i++) { /* Vulkan runtime passes us shaders in stage order, so the FS will always
result = panvk_compile_shader(dev, &infos[i], state, pAllocator, * be last if it exists. Iterate shaders in reverse order to ensure FS is
* processed before VS. */
for (i = shader_count - 1; i >= 0; i--) {
uint32_t *noperspective_varyings_ptr =
use_static_noperspective ? &noperspective_varyings : NULL;
result = panvk_compile_shader(dev, &infos[i], state,
noperspective_varyings_ptr,
pAllocator,
&shaders_out[i]); &shaders_out[i]);
/* Clean up NIR for the current shader */ /* Clean up NIR for the current shader */
@ -949,6 +963,16 @@ panvk_compile_shaders(struct vk_device *vk_dev, uint32_t shader_count,
if (result != VK_SUCCESS) if (result != VK_SUCCESS)
goto err_cleanup; goto err_cleanup;
/* If we are linking VS and FS, we can use the static interpolation
* qualifiers from the FS in the VS. */
if (infos[i].nir->info.stage == MESA_SHADER_FRAGMENT) {
struct panvk_shader *shader =
container_of(shaders_out[i], struct panvk_shader, vk);
use_static_noperspective = true;
noperspective_varyings = shader->info.varyings.noperspective;
}
} }
/* TODO: If we get multiple shaders here, we can perform part of the link /* TODO: If we get multiple shaders here, we can perform part of the link