From 90a31051f50ebaeb69046dd4b37c38d8e1d5f5fd Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Fri, 1 May 2026 10:26:37 -0400 Subject: [PATCH] lavapipe: rework immutable samplers samplers can be destroyed whenever, which makes it problematic to store the pointers into descriptor layouts for embedded samplers. instead, directly store the descriptor info into the layout, since this is all constant data which is unaffected by object lifetimes cc: mesa-stable (cherry picked from commit 1da8528bbcbad7b9f1a07d622a5c52c9675d0c5e) Part-of: --- .pick_status.json | 2 +- .../frontends/lavapipe/lvp_descriptor_set.c | 24 +++++--- src/gallium/frontends/lavapipe/lvp_execute.c | 58 +++---------------- src/gallium/frontends/lavapipe/lvp_pipeline.c | 36 +++++------- src/gallium/frontends/lavapipe/lvp_private.h | 3 +- 5 files changed, 39 insertions(+), 84 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index 5f0824240de..a1f5e011d05 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -4894,7 +4894,7 @@ "description": "lavapipe: rework immutable samplers", "nominated": true, "nomination_type": 1, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": null, "notes": null diff --git a/src/gallium/frontends/lavapipe/lvp_descriptor_set.c b/src/gallium/frontends/lavapipe/lvp_descriptor_set.c index edbaf8ce01c..82d07641a7e 100644 --- a/src/gallium/frontends/lavapipe/lvp_descriptor_set.c +++ b/src/gallium/frontends/lavapipe/lvp_descriptor_set.c @@ -86,7 +86,8 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateDescriptorSetLayout( size_t size = sizeof(struct lvp_descriptor_set_layout) + num_bindings * sizeof(set_layout->binding[0]) + - immutable_sampler_count * sizeof(struct lvp_sampler *); + immutable_sampler_count * sizeof(struct lp_descriptor) + + immutable_sampler_count * sizeof(struct vk_ycbcr_conversion_state); set_layout = vk_descriptor_set_layout_zalloc(&device->vk, size, pCreateInfo); if (!set_layout) @@ -94,8 +95,9 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateDescriptorSetLayout( set_layout->immutable_sampler_count = immutable_sampler_count; /* We just allocate all the samplers at the end of the struct */ - struct lvp_sampler **samplers = - (struct lvp_sampler **)&set_layout->binding[num_bindings]; + struct lp_descriptor *samplers = + (struct lp_descriptor *)&set_layout->binding[num_bindings]; + struct vk_ycbcr_conversion_state *ycbcr = (void*)(samplers + immutable_sampler_count); set_layout->binding_count = num_bindings; set_layout->shader_stages = 0; @@ -136,11 +138,17 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateDescriptorSetLayout( uint8_t max_plane_count = 1; if (binding_has_immutable_samplers(binding)) { set_layout->binding[b].immutable_samplers = samplers; + set_layout->binding[b].immutable_ycbcr = ycbcr; samplers += binding->descriptorCount; + ycbcr += binding->descriptorCount; for (uint32_t i = 0; i < binding->descriptorCount; i++) { VK_FROM_HANDLE(lvp_sampler, sampler, binding->pImmutableSamplers[i]); - set_layout->binding[b].immutable_samplers[i] = sampler; + set_layout->binding[b].immutable_samplers[i] = sampler->desc; + if (sampler->vk.ycbcr_conversion) + set_layout->binding[b].immutable_ycbcr[i] = sampler->vk.ycbcr_conversion->state; + else + memset(&set_layout->binding[b].immutable_ycbcr[i], 0, sizeof(struct vk_ycbcr_conversion_state)); const uint8_t sampler_plane_count = sampler->vk.ycbcr_conversion ? vk_format_get_plane_count(sampler->vk.ycbcr_conversion->state.format) : 1; if (max_plane_count < sampler_plane_count) @@ -366,11 +374,9 @@ lvp_descriptor_set_create(struct lvp_device *device, desc += bind_layout->descriptor_index; for (uint32_t sampler_index = 0; sampler_index < bind_layout->array_size; sampler_index++) { - if (bind_layout->immutable_samplers[sampler_index]) { - for (uint32_t s = 0; s < bind_layout->stride; s++) { - int idx = sampler_index * bind_layout->stride + s; - desc[idx] = bind_layout->immutable_samplers[sampler_index]->desc; - } + for (uint32_t s = 0; s < bind_layout->stride; s++) { + int idx = sampler_index * bind_layout->stride + s; + desc[idx] = bind_layout->immutable_samplers[sampler_index]; } } } diff --git a/src/gallium/frontends/lavapipe/lvp_execute.c b/src/gallium/frontends/lavapipe/lvp_execute.c index d08ed49d736..43c4676f012 100644 --- a/src/gallium/frontends/lavapipe/lvp_execute.c +++ b/src/gallium/frontends/lavapipe/lvp_execute.c @@ -4221,46 +4221,6 @@ handle_descriptor_buffers(struct vk_cmd_queue_entry *cmd, struct rendering_state } } -static bool -descriptor_layouts_equal(const struct lvp_descriptor_set_layout *a, const struct lvp_descriptor_set_layout *b) -{ - const uint8_t *pa = (const uint8_t*)a, *pb = (const uint8_t*)b; - uint32_t hash_start_offset = sizeof(struct vk_descriptor_set_layout); - uint32_t binding_offset = offsetof(struct lvp_descriptor_set_layout, binding); - /* base equal */ - if (memcmp(pa + hash_start_offset, pb + hash_start_offset, binding_offset - hash_start_offset)) - return false; - - /* bindings equal */ - if (a->binding_count != b->binding_count) - return false; - size_t binding_size = a->binding_count * sizeof(struct lvp_descriptor_set_binding_layout); - const struct lvp_descriptor_set_binding_layout *la = a->binding; - const struct lvp_descriptor_set_binding_layout *lb = b->binding; - if (memcmp(la, lb, binding_size)) { - for (unsigned i = 0; i < a->binding_count; i++) { - if (memcmp(&la[i], &lb[i], offsetof(struct lvp_descriptor_set_binding_layout, immutable_samplers))) - return false; - } - } - - /* immutable sampler equal */ - if (a->immutable_sampler_count != b->immutable_sampler_count) - return false; - if (a->immutable_sampler_count) { - size_t sampler_size = a->immutable_sampler_count * sizeof(struct lvp_sampler *); - if (memcmp(pa + binding_offset + binding_size, pb + binding_offset + binding_size, sampler_size)) { - struct lvp_sampler **sa = (struct lvp_sampler **)(pa + binding_offset); - struct lvp_sampler **sb = (struct lvp_sampler **)(pb + binding_offset); - for (unsigned i = 0; i < a->immutable_sampler_count; i++) { - if (memcmp(sa[i], sb[i], sizeof(struct lvp_sampler))) - return false; - } - } - } - return true; -} - static void bind_db_samplers(struct rendering_state *state, enum lvp_pipeline_type pipeline_type, unsigned set) { @@ -4291,16 +4251,14 @@ bind_db_samplers(struct rendering_state *state, enum lvp_pipeline_type pipeline_ desc += bind_layout->descriptor_index; for (uint32_t sampler_index = 0; sampler_index < bind_layout->array_size; sampler_index++) { - if (bind_layout->immutable_samplers[sampler_index]) { - struct lp_descriptor *immutable_desc = &bind_layout->immutable_samplers[sampler_index]->desc; - desc[sampler_index].sampler = immutable_desc->sampler; - desc[sampler_index].texture.sampler_index = immutable_desc->texture.sampler_index; - if (pipeline_type == LVP_PIPELINE_RAY_TRACING) { - did_update |= BITFIELD_BIT(MESA_SHADER_RAYGEN); - } else { - u_foreach_bit(stage, set_layout->shader_stages) - did_update |= BITFIELD_BIT(vk_to_mesa_shader_stage(1<immutable_samplers[sampler_index]; + desc[sampler_index].sampler = immutable_desc->sampler; + desc[sampler_index].texture.sampler_index = immutable_desc->texture.sampler_index; + if (pipeline_type == LVP_PIPELINE_RAY_TRACING) { + did_update |= BITFIELD_BIT(MESA_SHADER_RAYGEN); + } else { + u_foreach_bit(stage, set_layout->shader_stages) + did_update |= BITFIELD_BIT(vk_to_mesa_shader_stage(1<immutable_samplers) return NULL; - struct vk_ycbcr_conversion *ycbcr_conversion = binding_layout->immutable_samplers[array_index]->vk.ycbcr_conversion; - return ycbcr_conversion ? &ycbcr_conversion->state : NULL; + return binding_layout->immutable_ycbcr[array_index].format ? &binding_layout->immutable_ycbcr[array_index] : NULL; } /* pipeline is NULL for shader objects. */ @@ -636,7 +635,7 @@ layouts_equal(const struct lvp_descriptor_set_layout *a, const struct lvp_descri { const uint8_t *pa = (const uint8_t*)a, *pb = (const uint8_t*)b; uint32_t hash_start_offset = sizeof(struct vk_descriptor_set_layout); - uint32_t binding_offset = offsetof(struct lvp_descriptor_set_layout, binding); + uint32_t binding_offset = offsetof(struct lvp_descriptor_set_layout, immutable_set); /* base equal */ if (memcmp(pa + hash_start_offset, pb + hash_start_offset, binding_offset - hash_start_offset)) return false; @@ -644,31 +643,22 @@ layouts_equal(const struct lvp_descriptor_set_layout *a, const struct lvp_descri /* bindings equal */ if (a->binding_count != b->binding_count) return false; + if (a->immutable_sampler_count != b->immutable_sampler_count) + return false; size_t binding_size = a->binding_count * sizeof(struct lvp_descriptor_set_binding_layout); const struct lvp_descriptor_set_binding_layout *la = a->binding; const struct lvp_descriptor_set_binding_layout *lb = b->binding; - if (memcmp(la, lb, binding_size)) { - for (unsigned i = 0; i < a->binding_count; i++) { - if (memcmp(&la[i], &lb[i], offsetof(struct lvp_descriptor_set_binding_layout, immutable_samplers))) - return false; - } + if (!memcmp(la, lb, binding_size)) + return true; + for (unsigned i = 0; i < a->binding_count; i++) { + if (memcmp(&la[i], &lb[i], offsetof(struct lvp_descriptor_set_binding_layout, immutable_samplers))) + return false; } - - /* immutable sampler equal */ - if (a->immutable_sampler_count != b->immutable_sampler_count) + if (!a->immutable_sampler_count) + return true; + if (memcmp(la->immutable_samplers, lb->immutable_samplers, a->immutable_sampler_count * sizeof(struct lp_descriptor))) return false; - if (a->immutable_sampler_count) { - size_t sampler_size = a->immutable_sampler_count * sizeof(struct lvp_sampler *); - if (memcmp(pa + binding_offset + binding_size, pb + binding_offset + binding_size, sampler_size)) { - struct lvp_sampler **sa = (struct lvp_sampler **)(pa + binding_offset); - struct lvp_sampler **sb = (struct lvp_sampler **)(pb + binding_offset); - for (unsigned i = 0; i < a->immutable_sampler_count; i++) { - if (memcmp(sa[i], sb[i], sizeof(struct lvp_sampler))) - return false; - } - } - } - return true; + return !memcmp(la->immutable_ycbcr, lb->immutable_ycbcr, a->immutable_sampler_count * sizeof(struct vk_ycbcr_conversion_state)); } #endif diff --git a/src/gallium/frontends/lavapipe/lvp_private.h b/src/gallium/frontends/lavapipe/lvp_private.h index 6dc5193d7d9..646ca46bdde 100644 --- a/src/gallium/frontends/lavapipe/lvp_private.h +++ b/src/gallium/frontends/lavapipe/lvp_private.h @@ -331,7 +331,8 @@ struct lvp_descriptor_set_binding_layout { uint32_t uniform_block_size; /* Immutable samplers (or NULL if no immutable samplers) */ - struct lvp_sampler **immutable_samplers; + struct lp_descriptor *immutable_samplers; + struct vk_ycbcr_conversion_state *immutable_ycbcr; }; struct lvp_descriptor_set_layout {