Module: Mesa
Branch: main
Commit: e0d907f56fd84c119af22d6b4d14c52d99fd7b0c
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=e0d907f56fd84c119af22d6b4d14c52d99fd7b0c

Author: Faith Ekstrand <faith.ekstr...@collabora.com>
Date:   Fri Jan 12 13:53:30 2024 -0600

nvk: Rework descriptor set binding

This prepares us for VK_EXT_graphics_pipeline_library by allowing null
descriptor sets to be bound and handling holes in pipeline layouts.  We
also add a set_dynamic_buffer_start map to the root descriptor table
which says where in dynamic_buffers each set starts.  This can be used
by the pipeline layout lowering in the case where we can't statically
the dynamic buffer index for a binding.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27048>

---

 src/nouveau/vulkan/nvk_cmd_buffer.c | 49 +++++++++++++++++++++++++++++--------
 src/nouveau/vulkan/nvk_cmd_buffer.h |  5 +++-
 2 files changed, 43 insertions(+), 11 deletions(-)

diff --git a/src/nouveau/vulkan/nvk_cmd_buffer.c 
b/src/nouveau/vulkan/nvk_cmd_buffer.c
index 33bbdf92df0..c20917bdb24 100644
--- a/src/nouveau/vulkan/nvk_cmd_buffer.c
+++ b/src/nouveau/vulkan/nvk_cmd_buffer.c
@@ -572,12 +572,29 @@ nvk_CmdBindDescriptorSets(VkCommandBuffer commandBuffer,
    struct nvk_descriptor_state *desc =
       nvk_get_descriptors_state(cmd, pipelineBindPoint);
 
+   /* Fro the Vulkan 1.3.275 spec:
+    *
+    *    "When binding a descriptor set (see Descriptor Set Binding) to
+    *    set number N...
+    *
+    *    If, additionally, the previously bound descriptor set for set
+    *    N was bound using a pipeline layout not compatible for set N,
+    *    then all bindings in sets numbered greater than N are
+    *    disturbed."
+    *
+    * This means that, if some earlier set gets bound in such a way that
+    * it changes set_dynamic_buffer_start[s], this binding is implicitly
+    * invalidated.  Therefore, we can always look at the current value
+    * of set_dynamic_buffer_start[s] as the base of our dynamic buffer
+    * range and it's only our responsibility to adjust all
+    * set_dynamic_buffer_start[p] for p > s as needed.
+    */
+   uint8_t dyn_buffer_start = desc->root.set_dynamic_buffer_start[firstSet];
+
    uint32_t next_dyn_offset = 0;
    for (uint32_t i = 0; i < descriptorSetCount; ++i) {
       unsigned s = i + firstSet;
       VK_FROM_HANDLE(nvk_descriptor_set, set, pDescriptorSets[i]);
-      const struct nvk_descriptor_set_layout *set_layout =
-         vk_to_nvk_descriptor_set_layout(pipeline_layout->set_layouts[s]);
 
       if (desc->sets[s] != set) {
          desc->root.sets[s] = nvk_descriptor_set_addr(set);
@@ -589,19 +606,31 @@ nvk_CmdBindDescriptorSets(VkCommandBuffer commandBuffer,
          desc->push_dirty &= ~BITFIELD_BIT(s);
       }
 
-      if (set_layout->dynamic_buffer_count > 0) {
-         const uint32_t dynamic_buffer_start =
-            nvk_descriptor_set_layout_dynbuf_start(pipeline_layout, s);
+      desc->root.set_dynamic_buffer_start[s] = dyn_buffer_start;
+
+      if (pipeline_layout->set_layouts[s] != NULL) {
+         const struct nvk_descriptor_set_layout *set_layout =
+            vk_to_nvk_descriptor_set_layout(pipeline_layout->set_layouts[s]);
 
-         for (uint32_t j = 0; j < set_layout->dynamic_buffer_count; j++) {
-            struct nvk_buffer_address addr = set->dynamic_buffers[j];
-            addr.base_addr += pDynamicOffsets[next_dyn_offset + j];
-            desc->root.dynamic_buffers[dynamic_buffer_start + j] = addr;
+         if (set != NULL && set_layout->dynamic_buffer_count > 0) {
+            for (uint32_t j = 0; j < set_layout->dynamic_buffer_count; j++) {
+               struct nvk_buffer_address addr = set->dynamic_buffers[j];
+               addr.base_addr += pDynamicOffsets[next_dyn_offset + j];
+               desc->root.dynamic_buffers[dyn_buffer_start + j] = addr;
+            }
+            next_dyn_offset += set->layout->dynamic_buffer_count;
          }
-         next_dyn_offset += set->layout->dynamic_buffer_count;
+
+         dyn_buffer_start += set_layout->dynamic_buffer_count;
+      } else {
+         assert(set == NULL);
       }
    }
+   assert(dyn_buffer_start <= NVK_MAX_DYNAMIC_BUFFERS);
    assert(next_dyn_offset <= dynamicOffsetCount);
+
+   for (uint32_t s = firstSet + descriptorSetCount; s < NVK_MAX_SETS; s++)
+      desc->root.set_dynamic_buffer_start[s] = dyn_buffer_start;
 }
 
 VKAPI_ATTR void VKAPI_CALL
diff --git a/src/nouveau/vulkan/nvk_cmd_buffer.h 
b/src/nouveau/vulkan/nvk_cmd_buffer.h
index ec6042e3c73..32a2065dea3 100644
--- a/src/nouveau/vulkan/nvk_cmd_buffer.h
+++ b/src/nouveau/vulkan/nvk_cmd_buffer.h
@@ -56,8 +56,11 @@ struct nvk_root_descriptor_table {
    /* Dynamic buffer bindings */
    struct nvk_buffer_address dynamic_buffers[NVK_MAX_DYNAMIC_BUFFERS];
 
+   /* Start index in dynamic_buffers where each set starts */
+   uint8_t set_dynamic_buffer_start[NVK_MAX_SETS];
+
    /* enfore alignment to 0x100 as needed pre pascal */
-   uint8_t __padding[0x20];
+   uint8_t __padding[0x18];
 };
 
 /* helper macro for computing root descriptor byte offsets */

Reply via email to