Repro for validation layer push descriptor bug
diff --git a/cube/cube.c b/cube/cube.c
index 6bf8f4a..17860a0 100644
--- a/cube/cube.c
+++ b/cube/cube.c
@@ -397,6 +397,7 @@
     PFN_vkQueuePresentKHR fpQueuePresentKHR;
     PFN_vkGetRefreshCycleDurationGOOGLE fpGetRefreshCycleDurationGOOGLE;
     PFN_vkGetPastPresentationTimingGOOGLE fpGetPastPresentationTimingGOOGLE;
+    PFN_vkCmdPushDescriptorSetKHR fpCmdPushDescriptorSetKHR;
     uint32_t swapchainImageCount;
     VkSwapchainKHR swapchain;
     SwapchainImageResources *swapchain_image_resources;
@@ -420,11 +421,11 @@
     struct texture_object staging_texture;
 
     VkCommandBuffer cmd;  // Buffer for initialization commands
-    VkPipelineLayout pipeline_layout;
-    VkDescriptorSetLayout desc_layout;
+    VkPipelineLayout pipeline_layout[2];
+    VkDescriptorSetLayout desc_layout[2];
     VkPipelineCache pipelineCache;
     VkRenderPass render_pass;
-    VkPipeline pipeline;
+    VkPipeline pipeline[2];
 
     mat4x4 projection_matrix;
     mat4x4 view_matrix;
@@ -605,6 +606,7 @@
 // Forward declarations:
 static void demo_resize(struct demo *demo);
 static void demo_create_surface(struct demo *demo);
+static void demo_push_descriptors(struct demo *demo, VkCommandBuffer cmd);
 
 static bool memory_type_from_properties(struct demo *demo, uint32_t typeBits, VkFlags requirements_mask, uint32_t *typeIndex) {
     // Search memtypes to find first index with those properties
@@ -779,8 +781,11 @@
         demo->CmdBeginDebugUtilsLabelEXT(cmd_buf, &label);
     }
 
-    vkCmdBindPipeline(cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, demo->pipeline);
-    vkCmdBindDescriptorSets(cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, demo->pipeline_layout, 0, 1,
+    vkCmdBindPipeline(cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, demo->pipeline[1]);
+    demo_push_descriptors(demo, cmd_buf);
+
+    vkCmdBindPipeline(cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, demo->pipeline[0]);
+    vkCmdBindDescriptorSets(cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, demo->pipeline_layout[0], 0, 1,
                             &demo->swapchain_image_resources[demo->current_buffer].descriptor_set, 0, NULL);
     VkViewport viewport;
     memset(&viewport, 0, sizeof(viewport));
@@ -818,6 +823,7 @@
     }
 
     vkCmdDraw(cmd_buf, 12 * 3, 1, 0, 0);
+
     if (demo->validate) {
         demo->CmdEndDebugUtilsLabelEXT(cmd_buf);
     }
@@ -1853,26 +1859,39 @@
                 .pImmutableSamplers = NULL,
             },
     };
-    const VkDescriptorSetLayoutCreateInfo descriptor_layout = {
-        .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
-        .pNext = NULL,
-        .bindingCount = 2,
-        .pBindings = layout_bindings,
-    };
-    VkResult U_ASSERT_ONLY err;
-
-    err = vkCreateDescriptorSetLayout(demo->device, &descriptor_layout, NULL, &demo->desc_layout);
-    assert(!err);
-
-    const VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = {
-        .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
-        .pNext = NULL,
-        .setLayoutCount = 1,
-        .pSetLayouts = &demo->desc_layout,
+    const VkDescriptorSetLayoutCreateInfo descriptor_layout[2] = {
+        [0] =
+            {
+                .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+                .pNext = NULL,
+                .bindingCount = 2,
+                .pBindings = layout_bindings,
+            },
+        [1] =
+            {
+                .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+                .pNext = NULL,
+                .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR,
+                .bindingCount = 2,
+                .pBindings = layout_bindings,
+            },
     };
 
-    err = vkCreatePipelineLayout(demo->device, &pPipelineLayoutCreateInfo, NULL, &demo->pipeline_layout);
-    assert(!err);
+    for (unsigned int i = 0; i < 2; i++) {
+        VkResult U_ASSERT_ONLY err;
+        err = vkCreateDescriptorSetLayout(demo->device, &descriptor_layout[i], NULL, &demo->desc_layout[i]);
+        assert(!err);
+
+        const VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = {
+            .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+            .pNext = NULL,
+            .setLayoutCount = 1,
+            .pSetLayouts = &demo->desc_layout[i],
+        };
+
+        err = vkCreatePipelineLayout(demo->device, &pPipelineLayoutCreateInfo, NULL, &demo->pipeline_layout[i]);
+        assert(!err);
+    }
 }
 
 static void demo_prepare_render_pass(struct demo *demo) {
@@ -2027,7 +2046,7 @@
 
     memset(&pipeline, 0, sizeof(pipeline));
     pipeline.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
-    pipeline.layout = demo->pipeline_layout;
+    pipeline.layout = demo->pipeline_layout[0];
 
     memset(&vi, 0, sizeof(vi));
     vi.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
@@ -2116,7 +2135,12 @@
 
     pipeline.renderPass = demo->render_pass;
 
-    err = vkCreateGraphicsPipelines(demo->device, demo->pipelineCache, 1, &pipeline, NULL, &demo->pipeline);
+    err = vkCreateGraphicsPipelines(demo->device, demo->pipelineCache, 1, &pipeline, NULL, &demo->pipeline[0]);
+    assert(!err);
+
+    pipeline.layout = demo->pipeline_layout[1];
+
+    err = vkCreateGraphicsPipelines(demo->device, demo->pipelineCache, 1, &pipeline, NULL, &demo->pipeline[1]);
     assert(!err);
 
     vkDestroyShaderModule(demo->device, demo->frag_shader_module, NULL);
@@ -2158,7 +2182,7 @@
                                               .pNext = NULL,
                                               .descriptorPool = demo->desc_pool,
                                               .descriptorSetCount = 1,
-                                              .pSetLayouts = &demo->desc_layout};
+                                              .pSetLayouts = &demo->desc_layout[0]};
 
     VkDescriptorBufferInfo buffer_info;
     buffer_info.offset = 0;
@@ -2194,6 +2218,38 @@
     }
 }
 
+static void demo_push_descriptors(struct demo *demo, VkCommandBuffer cmd) {
+    VkDescriptorImageInfo tex_descs[DEMO_TEXTURE_COUNT];
+    VkWriteDescriptorSet writes[2];
+
+    VkDescriptorBufferInfo buffer_info;
+    buffer_info.buffer = demo->swapchain_image_resources[demo->current_buffer].uniform_buffer;
+    buffer_info.offset = 0;
+    buffer_info.range = sizeof(struct vktexcube_vs_uniform);
+
+    memset(&tex_descs, 0, sizeof(tex_descs));
+    for (unsigned int i = 0; i < DEMO_TEXTURE_COUNT; i++) {
+        tex_descs[i].sampler = demo->textures[i].sampler;
+        tex_descs[i].imageView = demo->textures[i].view;
+        tex_descs[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+    }
+
+    memset(&writes, 0, sizeof(writes));
+
+    writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+    writes[0].descriptorCount = 1;
+    writes[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+    writes[0].pBufferInfo = &buffer_info;
+
+    writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+    writes[1].dstBinding = 1;
+    writes[1].descriptorCount = DEMO_TEXTURE_COUNT;
+    writes[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+    writes[1].pImageInfo = tex_descs;
+
+    demo->fpCmdPushDescriptorSetKHR(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, demo->pipeline_layout[1], 0, 2, writes);
+}
+
 static void demo_prepare_framebuffers(struct demo *demo) {
     VkImageView attachments[2];
     attachments[1] = demo->depth.view;
@@ -2340,11 +2396,14 @@
         }
         vkDestroyDescriptorPool(demo->device, demo->desc_pool, NULL);
 
-        vkDestroyPipeline(demo->device, demo->pipeline, NULL);
+        vkDestroyPipeline(demo->device, demo->pipeline[0], NULL);
+        vkDestroyPipeline(demo->device, demo->pipeline[1], NULL);
         vkDestroyPipelineCache(demo->device, demo->pipelineCache, NULL);
         vkDestroyRenderPass(demo->device, demo->render_pass, NULL);
-        vkDestroyPipelineLayout(demo->device, demo->pipeline_layout, NULL);
-        vkDestroyDescriptorSetLayout(demo->device, demo->desc_layout, NULL);
+        vkDestroyPipelineLayout(demo->device, demo->pipeline_layout[0], NULL);
+        vkDestroyPipelineLayout(demo->device, demo->pipeline_layout[1], NULL);
+        vkDestroyDescriptorSetLayout(demo->device, demo->desc_layout[0], NULL);
+        vkDestroyDescriptorSetLayout(demo->device, demo->desc_layout[1], NULL);
 
         for (i = 0; i < DEMO_TEXTURE_COUNT; i++) {
             vkDestroyImageView(demo->device, demo->textures[i].view, NULL);
@@ -2433,11 +2492,14 @@
     }
     vkDestroyDescriptorPool(demo->device, demo->desc_pool, NULL);
 
-    vkDestroyPipeline(demo->device, demo->pipeline, NULL);
+    vkDestroyPipeline(demo->device, demo->pipeline[0], NULL);
+    vkDestroyPipeline(demo->device, demo->pipeline[1], NULL);
     vkDestroyPipelineCache(demo->device, demo->pipelineCache, NULL);
     vkDestroyRenderPass(demo->device, demo->render_pass, NULL);
-    vkDestroyPipelineLayout(demo->device, demo->pipeline_layout, NULL);
-    vkDestroyDescriptorSetLayout(demo->device, demo->desc_layout, NULL);
+    vkDestroyPipelineLayout(demo->device, demo->pipeline_layout[0], NULL);
+    vkDestroyPipelineLayout(demo->device, demo->pipeline_layout[1], NULL);
+    vkDestroyDescriptorSetLayout(demo->device, demo->desc_layout[0], NULL);
+    vkDestroyDescriptorSetLayout(demo->device, demo->desc_layout[1], NULL);
 
     for (i = 0; i < DEMO_TEXTURE_COUNT; i++) {
         vkDestroyImageView(demo->device, demo->textures[i].view, NULL);
@@ -3446,6 +3508,9 @@
             if (!strcmp("VK_KHR_portability_subset", device_extensions[i].extensionName)) {
                 demo->extension_names[demo->enabled_extension_count++] = "VK_KHR_portability_subset";
             }
+            if (!strcmp(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, device_extensions[i].extensionName)) {
+                demo->extension_names[demo->enabled_extension_count++] = VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME;
+            }
             assert(demo->enabled_extension_count < 64);
         }
 
@@ -3740,6 +3805,7 @@
         GET_DEVICE_PROC_ADDR(demo->device, GetRefreshCycleDurationGOOGLE);
         GET_DEVICE_PROC_ADDR(demo->device, GetPastPresentationTimingGOOGLE);
     }
+    GET_DEVICE_PROC_ADDR(demo->device, CmdPushDescriptorSetKHR);
 
     vkGetDeviceQueue(demo->device, demo->graphics_queue_family_index, 0, &demo->graphics_queue);