pvr: Add support to copy descriptors on vkUpdateDescriptorSets()
authorKarmjit Mahil <Karmjit.Mahil@imgtec.com>
Fri, 28 Oct 2022 09:47:02 +0000 (10:47 +0100)
committerMarge Bot <emma+marge@anholt.net>
Fri, 17 Feb 2023 10:10:11 +0000 (10:10 +0000)
Signed-off-by: Karmjit Mahil <Karmjit.Mahil@imgtec.com>
Reviewed-by: Frank Binns <frank.binns@imgtec.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21332>

src/imagination/vulkan/pvr_descriptor_set.c

index ece7a60..385aee2 100644 (file)
@@ -1929,6 +1929,120 @@ static void pvr_write_descriptor_set(struct pvr_device *device,
    }
 }
 
+static void pvr_copy_descriptor_set(struct pvr_device *device,
+                                    const VkCopyDescriptorSet *copy_set)
+{
+   PVR_FROM_HANDLE(pvr_descriptor_set, src_set, copy_set->srcSet);
+   PVR_FROM_HANDLE(pvr_descriptor_set, dst_set, copy_set->dstSet);
+   const struct pvr_descriptor_set_layout_binding *src_binding =
+      pvr_get_descriptor_binding(src_set->layout, copy_set->srcBinding);
+   const struct pvr_descriptor_set_layout_binding *dst_binding =
+      pvr_get_descriptor_binding(dst_set->layout, copy_set->dstBinding);
+   struct pvr_descriptor_size_info size_info;
+   uint32_t *src_mem_ptr;
+   uint32_t *dst_mem_ptr;
+
+   switch (src_binding->type) {
+   case VK_DESCRIPTOR_TYPE_SAMPLER:
+      break;
+
+   case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+   case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+   case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+   case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+   case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
+   case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+   case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
+   case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
+   case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
+   case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
+      const uint32_t src_idx =
+         src_binding->descriptor_index + copy_set->srcArrayElement;
+      const uint32_t dst_idx =
+         dst_binding->descriptor_index + copy_set->dstArrayElement;
+
+      for (uint32_t j = 0; j < copy_set->descriptorCount; j++) {
+         assert(src_set->descriptors[src_idx + j].type == src_binding->type);
+
+         dst_set->descriptors[dst_idx + j] = src_set->descriptors[src_idx + j];
+      }
+
+      break;
+   }
+
+   default:
+      unreachable("Unknown descriptor type");
+      break;
+   }
+
+   /* Dynamic buffer descriptors don't have any data stored in the descriptor
+    * set memory. They only exist in the set->descriptors list which we've
+    * already updated above.
+    */
+   if (src_binding->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
+       src_binding->type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) {
+      return;
+   }
+
+   src_mem_ptr = src_set->pvr_bo->bo->map;
+   dst_mem_ptr = dst_set->pvr_bo->bo->map;
+
+   /* From the Vulkan 1.3.232 spec VUID-VkCopyDescriptorSet-dstBinding-02632:
+    *
+    *    The type of dstBinding within dstSet must be equal to the type of
+    *    srcBinding within srcSet.
+    *
+    * So both bindings have the same descriptor size and we don't need to
+    * handle size differences.
+    */
+   pvr_descriptor_size_info_init(device, src_binding->type, &size_info);
+
+   assert(src_binding->shader_stage_mask == dst_binding->shader_stage_mask);
+
+   u_foreach_bit (stage, dst_binding->shader_stage_mask) {
+      uint16_t src_secondary_offset;
+      uint16_t dst_secondary_offset;
+      uint16_t src_primary_offset;
+      uint16_t dst_primary_offset;
+
+      /* Offset calculation functions expect descriptor_index to be
+       * binding relative not layout relative.
+       */
+      src_primary_offset =
+         pvr_get_descriptor_primary_offset(device,
+                                           src_set->layout,
+                                           src_binding,
+                                           stage,
+                                           copy_set->srcArrayElement);
+      dst_primary_offset =
+         pvr_get_descriptor_primary_offset(device,
+                                           dst_set->layout,
+                                           dst_binding,
+                                           stage,
+                                           copy_set->dstArrayElement);
+      src_secondary_offset =
+         pvr_get_descriptor_secondary_offset(device,
+                                             src_set->layout,
+                                             src_binding,
+                                             stage,
+                                             copy_set->srcArrayElement);
+      dst_secondary_offset =
+         pvr_get_descriptor_secondary_offset(device,
+                                             dst_set->layout,
+                                             dst_binding,
+                                             stage,
+                                             copy_set->dstArrayElement);
+
+      memcpy(dst_mem_ptr + dst_primary_offset,
+             src_mem_ptr + src_primary_offset,
+             size_info.primary * 4U * copy_set->descriptorCount);
+
+      memcpy(dst_mem_ptr + dst_secondary_offset,
+             src_mem_ptr + src_secondary_offset,
+             size_info.secondary * 4U * copy_set->descriptorCount);
+   }
+}
+
 void pvr_UpdateDescriptorSets(VkDevice _device,
                               uint32_t descriptorWriteCount,
                               const VkWriteDescriptorSet *pDescriptorWrites,
@@ -1940,6 +2054,6 @@ void pvr_UpdateDescriptorSets(VkDevice _device,
    for (uint32_t i = 0; i < descriptorWriteCount; i++)
       pvr_write_descriptor_set(device, &pDescriptorWrites[i]);
 
-   if (descriptorCopyCount > 0)
-      pvr_finishme("Descriptor copying support missing\n");
+   for (uint32_t i = 0; i < descriptorCopyCount; i++)
+      pvr_copy_descriptor_set(device, &pDescriptorCopies[i]);
 }