From b4b7b4764f75ab0c1446a317947cb56b85f001ef Mon Sep 17 00:00:00 2001
From: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Date: Thu, 24 Oct 2024 11:01:28 +0300
Subject: [PATCH 1/2] framework: add a way to enable descriptor_indexing

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
---
 include/tapi/t_def.h               |  2 ++
 src/framework/test/t_phase_setup.c | 49 ++++++++++++++++++++++--------
 2 files changed, 39 insertions(+), 12 deletions(-)

diff --git a/include/tapi/t_def.h b/include/tapi/t_def.h
index bcba61df..4d37bb1d 100644
--- a/include/tapi/t_def.h
+++ b/include/tapi/t_def.h
@@ -93,6 +93,8 @@ struct test_def {
 
     const bool robust_image_access;
 
+    const bool descriptor_indexing;
+
     /// \brief Private data for the test framework.
     ///
     /// Test authors shouldn't touch this struct.
diff --git a/src/framework/test/t_phase_setup.c b/src/framework/test/t_phase_setup.c
index ba54f8ab..95233dd9 100644
--- a/src/framework/test/t_phase_setup.c
+++ b/src/framework/test/t_phase_setup.c
@@ -317,7 +317,9 @@ t_setup_descriptor_pool(void)
     const VkDescriptorPoolCreateInfo create_info = {
         .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
         .pNext = NULL,
-        .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
+        .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT |
+                 (t->def->descriptor_indexing ?
+                  VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT : 0),
         .maxSets = 8,
         .poolSizeCount = ARRAY_LENGTH(pool_sizes),
         .pPoolSizes = pool_sizes
@@ -365,6 +367,15 @@ static VkBool32 debug_cb(VkDebugReportFlagsEXT flags,
     return false;
 }
 
+static void
+add_pnext(void *_prev, void *_next)
+{
+    VkBaseInStructure *prev = _prev, *next = _next;
+    while (prev->pNext != NULL)
+        prev = (VkBaseInStructure *) prev->pNext;
+    prev->pNext = next;
+}
+
 void
 t_setup_vulkan(void)
 {
@@ -589,9 +600,13 @@ t_setup_vulkan(void)
     VkPhysicalDeviceRobustness2FeaturesEXT pdr2f = {
       .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT,
     };
+    VkPhysicalDeviceDescriptorIndexingFeatures pddif = {
+      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES,
+      .pNext = &pdr2f,
+    };
     VkPhysicalDeviceFeatures2 pdf2 = {
       .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
-      .pNext = &pdr2f,
+      .pNext = &pddif,
     };
     vkGetPhysicalDeviceFeatures2(t->vk.physical_dev, &pdf2);
 
@@ -599,19 +614,29 @@ t_setup_vulkan(void)
       t_skipf("Test requested robust image access, "
               "but implementation does not support robustImageAccess2");
 
+
     pdr2f.robustImageAccess2 = pdr2f.robustImageAccess2 &&
                                t->def->robust_image_access;
 
-    res = vkCreateDevice(t->vk.physical_dev,
-        &(VkDeviceCreateInfo) {
-            .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
-            .queueCreateInfoCount = t->vk.queue_family_count,
-            .pQueueCreateInfos = qci,
-            .enabledExtensionCount = t->vk.device_extension_count,
-            .ppEnabledExtensionNames = ext_names,
-            .pEnabledFeatures = &pdf,
-            .pNext = t->def->robust_image_access ? &pdr2f : NULL,
-        }, NULL, &t->vk.device);
+    VkDeviceCreateInfo dci = {
+        .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
+        .queueCreateInfoCount = t->vk.queue_family_count,
+        .pQueueCreateInfos = qci,
+        .enabledExtensionCount = t->vk.device_extension_count,
+        .ppEnabledExtensionNames = ext_names,
+        .pEnabledFeatures = &pdf,
+    };
+
+    if (t->def->robust_image_access) {
+        pdr2f.pNext = NULL;
+        add_pnext(&dci, &pdr2f);
+    }
+    if (t->def->descriptor_indexing) {
+        pddif.pNext = NULL;
+        add_pnext(&dci, &pddif);
+    }
+
+    res = vkCreateDevice(t->vk.physical_dev, &dci, NULL, &t->vk.device);
     free(qci);
     free(ext_names);
     free(priorities);
-- 
GitLab


From 38d1afc18e3ee8423551c585433559ece466534d Mon Sep 17 00:00:00 2001
From: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Date: Thu, 24 Oct 2024 10:31:08 +0300
Subject: [PATCH 2/2] Add test for gitlab issue 12058

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
---
 src/tests/bug/gitlab-12058.c | 229 +++++++++++++++++++++++++++++++++++
 src/tests/meson.build        |   1 +
 2 files changed, 230 insertions(+)
 create mode 100644 src/tests/bug/gitlab-12058.c

diff --git a/src/tests/bug/gitlab-12058.c b/src/tests/bug/gitlab-12058.c
new file mode 100644
index 00000000..bcdc5f9e
--- /dev/null
+++ b/src/tests/bug/gitlab-12058.c
@@ -0,0 +1,229 @@
+// Copyright 2024 Intel Corporation
+// SPDX-License-Identifier: MIT
+
+/* This is a test for https://gitlab.freedesktop.org/mesa/mesa/-/issues/12058
+ *
+ * The issue is rather involved and only reproduces on DG2+.
+ *
+ * Push constants buffers allocated internally in the driver are bounded
+ * (lowest offset, highest offset) using the shader usage. Between 2 pipelines
+ * bound with different push constant layouts, if there is no push constant
+ * update (or other events updating the push constant buffer like descriptor
+ * binding, base workgroup offset, etc...), the push constant buffer is not
+ * reallocated missing that a new pipeline has been bound with a different
+ * push constant layout that would require a new reallocation to adjust for
+ * the new lowest offset access.
+ *
+ * Here we force the UPDATE_AFTER_BIND_BIT to ensure the driver access a part
+ * of the push constant buffers for descriptors and we have 2 pipelines with
+ * no push constant access and the other with push constant accesses. We bind
+ * the first pipeline so that the computed push constant buffer bounds are
+ * smaller than what the second pipeline will need.
+ */
+
+#include "tapi/t.h"
+
+#include "src/tests/bug/gitlab-12058-spirv.h"
+
+static void
+test(void)
+{
+    t_require_ext("VK_EXT_descriptor_indexing");
+
+    VkDescriptorBindingFlags binding_flags =
+        VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT;
+    VkDescriptorSetLayoutBindingFlagsCreateInfo binding_flags_info = {
+        .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO,
+        .bindingCount = 1,
+        .pBindingFlags = &binding_flags,
+    };
+
+    VkDescriptorSetLayout set_layout;
+
+    set_layout = qoCreateDescriptorSetLayout(
+        t_device,
+        .pNext = &binding_flags_info,
+        .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT,
+        .bindingCount = 1,
+        .pBindings = (VkDescriptorSetLayoutBinding[]) {
+            {
+                .binding = 0,
+                .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+                .descriptorCount = 1,
+                .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
+                .pImmutableSamplers = NULL,
+            },
+        });
+
+    VkPipelineLayout pipeline_layout = qoCreatePipelineLayout(
+        t_device,
+        .setLayoutCount = 1,
+        .pSetLayouts = &set_layout,
+        .pushConstantRangeCount = 1,
+        .pPushConstantRanges = &(VkPushConstantRange) {
+            .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
+            .offset = 0,
+            .size = 128,
+        });
+
+    VkShaderModule cs1 = qoCreateShaderModuleGLSL(
+        t_device, COMPUTE,
+
+        layout(push_constant) uniform Push {
+            uint data0;
+        };
+        layout(set = 0, binding = 0) buffer Storage {
+            uint storage[];
+        };
+
+        void main()
+        {
+            storage[0] = 42;
+        }
+    );
+    VkShaderModule cs2 = qoCreateShaderModuleGLSL(
+        t_device, COMPUTE,
+
+        layout(push_constant) uniform Push {
+            uint data0;
+        } push;
+        layout(set = 0, binding = 0) buffer Storage {
+            uint storage[];
+        };
+
+        void main()
+        {
+            storage[1] = push.data0;
+        }
+    );
+
+    VkPipeline pipeline1;
+    VkResult result = vkCreateComputePipelines(t_device, t_pipeline_cache, 1,
+        &(VkComputePipelineCreateInfo) {
+            .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
+            .pNext = NULL,
+            .stage = {
+                .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+                .stage = VK_SHADER_STAGE_COMPUTE_BIT,
+                .module = cs1,
+                .pName = "main",
+            },
+            .flags = 0,
+            .layout = pipeline_layout
+        }, NULL, &pipeline1);
+    t_assert(result == VK_SUCCESS);
+    t_cleanup_push_vk_pipeline(t_device, pipeline1);
+
+    VkPipeline pipeline2;
+    result = vkCreateComputePipelines(t_device, t_pipeline_cache, 1,
+        &(VkComputePipelineCreateInfo) {
+            .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
+            .pNext = NULL,
+            .stage = {
+                .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+                .stage = VK_SHADER_STAGE_COMPUTE_BIT,
+                .module = cs2,
+                .pName = "main",
+            },
+            .flags = 0,
+            .layout = pipeline_layout
+        }, NULL, &pipeline2);
+    t_assert(result == VK_SUCCESS);
+    t_cleanup_push_vk_pipeline(t_device, pipeline2);
+
+    VkDescriptorSet set =
+        qoAllocateDescriptorSet(t_device,
+                                .descriptorPool = t_descriptor_pool,
+                                .pSetLayouts = &set_layout);
+
+    VkBuffer buffer = qoCreateBuffer(t_device,
+        .size = 1024,
+        .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
+
+    VkDeviceMemory mem = qoAllocBufferMemory(t_device, buffer,
+        .properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
+    t_cleanup_push_vk_device_memory(t_device, mem);
+
+    qoBindBufferMemory(t_device, buffer, mem, 0);
+
+    vkUpdateDescriptorSets(t_device,
+        /*writeCount*/ 1,
+        (VkWriteDescriptorSet[]) {
+            {
+                .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+                .dstSet = set,
+                .dstBinding = 0,
+                .dstArrayElement = 0,
+                .descriptorCount = 1,
+                .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+                .pBufferInfo = &(VkDescriptorBufferInfo) {
+                    .buffer = buffer,
+                    .offset = 0,
+                    .range = VK_WHOLE_SIZE,
+                },
+            },
+        }, 0, NULL);
+
+    uint32_t data;
+
+    data = 43;
+    vkCmdPushConstants(t_cmd_buffer, pipeline_layout,
+                       VK_SHADER_STAGE_COMPUTE_BIT,
+                       0, sizeof(data), &data);
+
+    vkCmdBindDescriptorSets(t_cmd_buffer,
+                            VK_PIPELINE_BIND_POINT_COMPUTE,
+                            pipeline_layout, 0, 1,
+                            &set, 0, NULL);
+
+    vkCmdPipelineBarrier(t_cmd_buffer,
+                         VK_PIPELINE_STAGE_HOST_BIT,
+                         VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
+                         0, 0, NULL,
+                         1, &(VkBufferMemoryBarrier) {
+                             .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
+                             .srcAccessMask = 0,
+                             .dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
+                             .buffer = buffer,
+                             .offset = 0,
+                             .size = VK_WHOLE_SIZE,
+                         },
+                         0, NULL);
+
+    vkCmdBindPipeline(t_cmd_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline1);
+    vkCmdDispatch(t_cmd_buffer, 1, 1, 1);
+    vkCmdBindPipeline(t_cmd_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline2);
+    vkCmdDispatch(t_cmd_buffer, 1, 1, 1);
+
+    vkCmdPipelineBarrier(t_cmd_buffer,
+                         VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
+                         VK_PIPELINE_STAGE_HOST_BIT,
+                         0, 0, NULL,
+                         1, &(VkBufferMemoryBarrier) {
+                             .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
+                             .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
+                             .dstAccessMask = VK_ACCESS_HOST_READ_BIT,
+                             .buffer = buffer,
+                             .offset = 0,
+                             .size = VK_WHOLE_SIZE,
+                         },
+                         0, NULL);
+
+    qoEndCommandBuffer(t_cmd_buffer);
+    qoQueueSubmit(t_queue, 1, &t_cmd_buffer, VK_NULL_HANDLE);
+
+    qoQueueWaitIdle(t_queue);
+
+    uint32_t *ssbo_data = qoMapMemory(t_device, mem, 0, VK_WHOLE_SIZE, 0);
+
+    t_assert(ssbo_data[0] == 42);
+    t_assert(ssbo_data[1] == 43);
+}
+
+test_define {
+    .name = "bug.gitlab-12058",
+    .start = test,
+    .no_image = true,
+    .queue_setup = QUEUE_SETUP_COMPUTE,
+    .descriptor_indexing = true,
+};
diff --git a/src/tests/meson.build b/src/tests/meson.build
index 5196d4e1..8299c0c7 100644
--- a/src/tests/meson.build
+++ b/src/tests/meson.build
@@ -55,6 +55,7 @@ test_sources_with_spirv = [
   'bug/gitlab-6680.c',
   'bug/gitlab-9013.c',
   'bug/gitlab-11800.c',
+  'bug/gitlab-12058.c',
   'func/4-vertex-buffers.c',
   'func/depthstencil/basic.c',
   'func/depthstencil/arrayed-clear.c',
-- 
GitLab