From f47de306b85cde904a963b5807d061bdf9863ef7 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Mon, 26 May 2025 10:30:55 -0400 Subject: [PATCH] vulkan: pass enabled features to drivers for pipelines, we know enabled features. for classic shader objects, we do not. therefore, we want to plumb this through explicitly for drivers using common pipelines, rather than making drivers guess whether they can use the device features. Signed-off-by: Alyssa Rosenzweig Reviewed-by: Faith Ekstrand Part-of: --- src/asahi/vulkan/hk_shader.c | 7 ++++-- src/nouveau/vulkan/nvk_shader.c | 14 ++++++----- src/panfrost/vulkan/panvk_vX_shader.c | 35 +++++++++++++++------------ src/vulkan/runtime/vk_pipeline.c | 15 +++++++++--- src/vulkan/runtime/vk_shader.c | 5 ++-- src/vulkan/runtime/vk_shader.h | 19 +++++++++++---- 6 files changed, 61 insertions(+), 34 deletions(-) diff --git a/src/asahi/vulkan/hk_shader.c b/src/asahi/vulkan/hk_shader.c index 0e7f0b4d6f1..a21e849f290 100644 --- a/src/asahi/vulkan/hk_shader.c +++ b/src/asahi/vulkan/hk_shader.c @@ -30,6 +30,7 @@ #include "nir_xfb_info.h" #include "shader_enums.h" #include "vk_nir_convert_ycbcr.h" +#include "vk_physical_device_features.h" #include "vk_pipeline.h" #include "vk_pipeline_layout.h" #include "vk_shader.h" @@ -224,11 +225,12 @@ hk_populate_fs_key(struct hk_fs_key *key, static void hk_hash_graphics_state(struct vk_physical_device *device, const struct vk_graphics_pipeline_state *state, + const struct vk_features *features, VkShaderStageFlags stages, blake3_hash blake3_out) { struct mesa_blake3 blake3_ctx; _mesa_blake3_init(&blake3_ctx); - if (stages & VK_SHADER_STAGE_FRAGMENT_BIT) { + if (state && (stages & VK_SHADER_STAGE_FRAGMENT_BIT)) { struct hk_fs_key key; hk_populate_fs_key(&key, state); _mesa_blake3_update(&blake3_ctx, &key, sizeof(key)); @@ -1253,6 +1255,7 @@ static VkResult hk_compile_shaders(struct vk_device *vk_dev, uint32_t shader_count, struct vk_shader_compile_info *infos, const struct vk_graphics_pipeline_state *state, + const struct vk_features *features, const VkAllocationCallbacks *pAllocator, struct vk_shader **shaders_out) { @@ -1494,7 +1497,7 @@ const struct vk_device_shader_ops hk_device_shader_ops = { .get_nir_options = hk_get_nir_options, .get_spirv_options = hk_get_spirv_options, .preprocess_nir = hk_preprocess_nir, - .hash_graphics_state = hk_hash_graphics_state, + .hash_state = hk_hash_graphics_state, .compile = hk_compile_shaders, .deserialize = hk_deserialize_api_shader, .cmd_set_dynamic_graphics_state = vk_cmd_set_dynamic_graphics_state, diff --git a/src/nouveau/vulkan/nvk_shader.c b/src/nouveau/vulkan/nvk_shader.c index c998aabfe75..8f397bec013 100644 --- a/src/nouveau/vulkan/nvk_shader.c +++ b/src/nouveau/vulkan/nvk_shader.c @@ -247,14 +247,15 @@ nvk_populate_fs_key(struct nak_fs_key *key, } static void -nvk_hash_graphics_state(struct vk_physical_device *device, - const struct vk_graphics_pipeline_state *state, - VkShaderStageFlags stages, - blake3_hash blake3_out) +nvk_hash_state(struct vk_physical_device *device, + const struct vk_graphics_pipeline_state *state, + const struct vk_features *enabled_features, + VkShaderStageFlags stages, + blake3_hash blake3_out) { struct mesa_blake3 blake3_ctx; _mesa_blake3_init(&blake3_ctx); - if (stages & VK_SHADER_STAGE_FRAGMENT_BIT) { + if (state && (stages & VK_SHADER_STAGE_FRAGMENT_BIT)) { struct nak_fs_key key; nvk_populate_fs_key(&key, state); _mesa_blake3_update(&blake3_ctx, &key, sizeof(key)); @@ -1071,6 +1072,7 @@ nvk_compile_shaders(struct vk_device *vk_dev, uint32_t shader_count, struct vk_shader_compile_info *infos, const struct vk_graphics_pipeline_state *state, + const struct vk_features *enabled_features, const VkAllocationCallbacks* pAllocator, struct vk_shader **shaders_out) { @@ -1386,7 +1388,7 @@ const struct vk_device_shader_ops nvk_device_shader_ops = { .get_nir_options = nvk_get_nir_options, .get_spirv_options = nvk_get_spirv_options, .preprocess_nir = nvk_preprocess_nir, - .hash_graphics_state = nvk_hash_graphics_state, + .hash_state = nvk_hash_state, .compile = nvk_compile_shaders, .deserialize = nvk_deserialize_shader, .cmd_set_dynamic_graphics_state = vk_cmd_set_dynamic_graphics_state, diff --git a/src/panfrost/vulkan/panvk_vX_shader.c b/src/panfrost/vulkan/panvk_vX_shader.c index 51f0e8dbeb1..5b20a0ba4dc 100644 --- a/src/panfrost/vulkan/panvk_vX_shader.c +++ b/src/panfrost/vulkan/panvk_vX_shader.c @@ -436,26 +436,30 @@ panvk_preprocess_nir(UNUSED struct vk_physical_device *vk_pdev, } static void -panvk_hash_graphics_state(struct vk_physical_device *device, - const struct vk_graphics_pipeline_state *state, - VkShaderStageFlags stages, blake3_hash blake3_out) +panvk_hash_state(struct vk_physical_device *device, + const struct vk_graphics_pipeline_state *state, + const struct vk_features *enabled_features, + VkShaderStageFlags stages, blake3_hash blake3_out) { struct mesa_blake3 blake3_ctx; _mesa_blake3_init(&blake3_ctx); - /* This doesn't impact the shader compile but it does go in the - * panvk_shader and gets [de]serialized along with the binary so - * we need to hash it. - */ - bool sample_shading_enable = state->ms && state->ms->sample_shading_enable; - _mesa_blake3_update(&blake3_ctx, &sample_shading_enable, - sizeof(sample_shading_enable)); + if (state != NULL) { + /* This doesn't impact the shader compile but it does go in the + * panvk_shader and gets [de]serialized along with the binary so + * we need to hash it. + */ + bool sample_shading_enable = + state->ms && state->ms->sample_shading_enable; + _mesa_blake3_update(&blake3_ctx, &sample_shading_enable, + sizeof(sample_shading_enable)); - _mesa_blake3_update(&blake3_ctx, &state->rp->view_mask, - sizeof(state->rp->view_mask)); + _mesa_blake3_update(&blake3_ctx, &state->rp->view_mask, + sizeof(state->rp->view_mask)); - if (state->ial) - _mesa_blake3_update(&blake3_ctx, state->ial, sizeof(*state->ial)); + if (state->ial) + _mesa_blake3_update(&blake3_ctx, state->ial, sizeof(*state->ial)); + } _mesa_blake3_final(&blake3_ctx, blake3_out); } @@ -1307,6 +1311,7 @@ static VkResult panvk_compile_shaders(struct vk_device *vk_dev, uint32_t shader_count, struct vk_shader_compile_info *infos, const struct vk_graphics_pipeline_state *state, + const struct vk_features *enabled_features, const VkAllocationCallbacks *pAllocator, struct vk_shader **shaders_out) { @@ -1950,7 +1955,7 @@ const struct vk_device_shader_ops panvk_per_arch(device_shader_ops) = { .get_nir_options = panvk_get_nir_options, .get_spirv_options = panvk_get_spirv_options, .preprocess_nir = panvk_preprocess_nir, - .hash_graphics_state = panvk_hash_graphics_state, + .hash_state = panvk_hash_state, .compile = panvk_compile_shaders, .deserialize = panvk_deserialize_shader, .cmd_set_dynamic_graphics_state = vk_cmd_set_dynamic_graphics_state, diff --git a/src/vulkan/runtime/vk_pipeline.c b/src/vulkan/runtime/vk_pipeline.c index ce7a37c3151..8212c311c21 100644 --- a/src/vulkan/runtime/vk_pipeline.c +++ b/src/vulkan/runtime/vk_pipeline.c @@ -32,6 +32,7 @@ #include "vk_log.h" #include "vk_nir.h" #include "vk_physical_device.h" +#include "vk_physical_device_features.h" #include "vk_pipeline_layout.h" #include "vk_shader.h" #include "vk_shader_module.h" @@ -1237,8 +1238,8 @@ vk_graphics_pipeline_compile_shaders(struct vk_device *device, } blake3_hash state_blake3; - ops->hash_graphics_state(device->physical, state, - part_stages, state_blake3); + ops->hash_state(device->physical, state, &device->enabled_features, + part_stages, state_blake3); _mesa_blake3_update(&blake3_ctx, state_blake3, sizeof(state_blake3)); _mesa_blake3_update(&blake3_ctx, layout_blake3, sizeof(layout_blake3)); @@ -1420,7 +1421,7 @@ vk_graphics_pipeline_compile_shaders(struct vk_device *device, struct vk_shader *shaders[MESA_VK_MAX_GRAPHICS_PIPELINE_STAGES]; result = ops->compile(device, partition[p + 1] - partition[p], &infos[partition[p]], - state, + state, &device->enabled_features, &device->alloc, &shaders[partition[p]]); if (result != VK_SUCCESS) @@ -1982,6 +1983,12 @@ vk_pipeline_compile_compute_stage(struct vk_device *device, _mesa_blake3_update(&blake3_ctx, &shader_flags, sizeof(shader_flags)); + blake3_hash features_blake3; + ops->hash_state(device->physical, NULL /* state */, + &device->enabled_features, VK_SHADER_STAGE_COMPUTE_BIT, + features_blake3); + _mesa_blake3_update(&blake3_ctx, features_blake3, sizeof(features_blake3)); + for (uint32_t i = 0; i < pipeline_layout->set_count; i++) { if (pipeline_layout->set_layouts[i] != NULL) { _mesa_blake3_update(&blake3_ctx, @@ -2040,7 +2047,7 @@ vk_pipeline_compile_compute_stage(struct vk_device *device, struct vk_shader *shader; result = ops->compile(device, 1, &compile_info, NULL, - &device->alloc, &shader); + &device->enabled_features, &device->alloc, &shader); if (result != VK_SUCCESS) return result; diff --git a/src/vulkan/runtime/vk_shader.c b/src/vulkan/runtime/vk_shader.c index 3f5ed17fe3d..0594be4d41a 100644 --- a/src/vulkan/runtime/vk_shader.c +++ b/src/vulkan/runtime/vk_shader.c @@ -30,6 +30,7 @@ #include "vk_device.h" #include "vk_nir.h" #include "vk_physical_device.h" +#include "vk_physical_device_features.h" #include "vk_pipeline.h" #include "util/mesa-sha1.h" @@ -507,7 +508,7 @@ vk_common_CreateShadersEXT(VkDevice _device, struct vk_shader *shader; result = ops->compile(device, 1, &info, NULL /* state */, - pAllocator, &shader); + NULL /* features */, pAllocator, &shader); if (result != VK_SUCCESS) break; @@ -554,7 +555,7 @@ vk_common_CreateShadersEXT(VkDevice _device, struct vk_shader *shaders[VK_MAX_LINKED_SHADER_STAGES]; result = ops->compile(device, linked_count, infos, NULL /* state */, - pAllocator, shaders); + NULL /* features */, pAllocator, shaders); if (result == VK_SUCCESS) { for (uint32_t l = 0; l < linked_count; l++) pShaders[linked[l].idx] = vk_shader_to_handle(shaders[l]); diff --git a/src/vulkan/runtime/vk_shader.h b/src/vulkan/runtime/vk_shader.h index b01d4ddfa9d..8a0cc13318b 100644 --- a/src/vulkan/runtime/vk_shader.h +++ b/src/vulkan/runtime/vk_shader.h @@ -41,6 +41,7 @@ struct vk_device; struct vk_descriptor_set_layout; struct vk_dynamic_graphics_state; struct vk_graphics_pipeline_state; +struct vk_features; struct vk_physical_device; struct vk_pipeline; struct vk_pipeline_robustness_state; @@ -213,15 +214,19 @@ struct vk_device_shader_ops { */ bool link_geom_stages; - /** Hash a vk_graphics_state object + /** Hash a vk_graphics_state object and a vk_features object. * * This callback hashes whatever bits of vk_graphics_pipeline_state might * be used to compile a shader in one of the given stages. + * + * state may be null, indicating that all state is dynamic. enabled_features + * is always non-NULL. */ - void (*hash_graphics_state)(struct vk_physical_device *device, - const struct vk_graphics_pipeline_state *state, - VkShaderStageFlags stages, - blake3_hash blake3_out); + void (*hash_state)(struct vk_physical_device *device, + const struct vk_graphics_pipeline_state *state, + const struct vk_features *enabled_features, + VkShaderStageFlags stages, + blake3_hash blake3_out); /** Compile (and potentially link) a set of shaders * @@ -230,6 +235,9 @@ struct vk_device_shader_ops { * them. We also guarantee that the shaders occur in the call in Vulkan * pipeline stage order as dictated by vk_shader_cmp_graphics_stages(). * + * If state/enabled_features is NULL, the driver must conservatively assume + * all state is dynamic / all features are enabled respectively. + * * This callback consumes all input NIR shaders, regardless of whether or * not it was successful. */ @@ -237,6 +245,7 @@ struct vk_device_shader_ops { uint32_t shader_count, struct vk_shader_compile_info *infos, const struct vk_graphics_pipeline_state *state, + const struct vk_features *enabled_features, const VkAllocationCallbacks* pAllocator, struct vk_shader **shaders_out);