v3dv: implement VK_KHR_maintenance3
authorIago Toral Quiroga <itoral@igalia.com>
Tue, 25 May 2021 08:49:06 +0000 (10:49 +0200)
committerMarge Bot <eric+marge@anholt.net>
Wed, 26 May 2021 07:18:19 +0000 (07:18 +0000)
We don't have any special restrictions associated with the number
of descriptors in a set other than maybe not exceeding what we can
put in a single memory allocation, so in practice, applications will
be limited by the per-stage contraints defined by other Vulkan limits.

Reviewed-by: Alejandro PiƱeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10970>

docs/features.txt
src/broadcom/vulkan/v3dv_descriptor_set.c
src/broadcom/vulkan/v3dv_device.c
src/broadcom/vulkan/v3dv_private.h

index 28eb5ac..9a50e06 100644 (file)
@@ -437,7 +437,7 @@ Vulkan 1.1 -- all DONE: anv, lvp, radv, tu, vn
   VK_KHR_get_physical_device_properties2                DONE (anv, lvp, radv, tu, v3dv, vn)
   VK_KHR_maintenance1                                   DONE (anv, lvp, radv, tu, v3dv, vn)
   VK_KHR_maintenance2                                   DONE (anv, lvp, radv, tu, v3dv, vn)
-  VK_KHR_maintenance3                                   DONE (anv, lvp, radv, tu, vn)
+  VK_KHR_maintenance3                                   DONE (anv, lvp, radv, tu, v3dv, vn)
   VK_KHR_multiview                                      DONE (anv, lvp, radv, tu, vn)
   VK_KHR_relaxed_block_layout                           DONE (anv, lvp, radv, tu, vn)
   VK_KHR_sampler_ycbcr_conversion                       DONE (anv, radv, tu, vn)
index 3487d70..72a0683 100644 (file)
@@ -49,6 +49,14 @@ descriptor_bo_size(VkDescriptorType type)
    }
 }
 
+uint32_t
+v3dv_max_descriptor_bo_size()
+{
+   return MAX3(sizeof(struct v3dv_sampler_descriptor),
+               sizeof(struct v3dv_combined_image_sampler_descriptor),
+               sizeof(struct v3dv_sampled_image_descriptor));
+}
+
 /*
  * For a given descriptor defined by the descriptor_set it belongs, its
  * binding layout, and array_index, it returns the map region assigned to it
@@ -1096,3 +1104,46 @@ v3dv_UpdateDescriptorSets(VkDevice  _device,
       }
    }
 }
+
+void
+v3dv_GetDescriptorSetLayoutSupport(
+   VkDevice device,
+   const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
+   VkDescriptorSetLayoutSupport *pSupport)
+{
+   VkDescriptorSetLayoutBinding *bindings = NULL;
+   VkResult result = vk_create_sorted_bindings(
+      pCreateInfo->pBindings, pCreateInfo->bindingCount, &bindings);
+   if (result != VK_SUCCESS) {
+      pSupport->supported = false;
+      return;
+   }
+
+   bool supported = true;
+
+   uint32_t desc_host_size = sizeof(struct v3dv_descriptor);
+   uint32_t host_size = sizeof(struct v3dv_descriptor_set);
+   uint32_t bo_size = 0;
+   for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {
+      const VkDescriptorSetLayoutBinding *binding = bindings + i;
+
+      if ((UINT32_MAX - host_size) / desc_host_size < binding->descriptorCount) {
+         supported = false;
+         break;
+      }
+
+      uint32_t desc_bo_size = descriptor_bo_size(binding->descriptorType);
+      if (desc_bo_size > 0 &&
+          (UINT32_MAX - bo_size) / desc_bo_size < binding->descriptorCount) {
+         supported = false;
+         break;
+      }
+
+      host_size += binding->descriptorCount * desc_host_size;
+      bo_size += binding->descriptorCount * desc_bo_size;
+   }
+
+   free(bindings);
+
+   pSupport->supported = supported;
+}
index 338b2df..ff758ad 100644 (file)
@@ -134,6 +134,7 @@ get_device_extensions(const struct v3dv_physical_device *device,
       .KHR_external_memory_fd              = true,
       .KHR_maintenance1                    = true,
       .KHR_maintenance2                    = true,
+      .KHR_maintenance3                    = true,
 #ifdef V3DV_HAS_SURFACE
       .KHR_swapchain                       = true,
 #endif
@@ -1250,6 +1251,29 @@ v3dv_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
             VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES;
          break;
       }
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES: {
+         VkPhysicalDeviceMaintenance3Properties *props =
+            (VkPhysicalDeviceMaintenance3Properties *)ext;
+         /* We don't really have special restrictions for the maximum
+          * descriptors per set, other than maybe not exceeding the limits
+          * of addressable memory in a single allocation on either the host
+          * or the GPU. This will be a much larger limit than any of the
+          * per-stage limits already available in Vulkan though, so in practice,
+          * it is not expected to limit anything beyond what is already
+          * constrained through per-stage limits.
+          */
+         uint32_t max_host_descriptors =
+            (UINT32_MAX - sizeof(struct v3dv_descriptor_set)) /
+            sizeof(struct v3dv_descriptor);
+         uint32_t max_gpu_descriptors =
+            (UINT32_MAX / v3dv_max_descriptor_bo_size());
+         props->maxPerSetDescriptors =
+            MIN2(max_host_descriptors, max_gpu_descriptors);
+
+         /* Minimum required by the spec */
+         props->maxMemoryAllocationSize = MAX_MEMORY_ALLOCATION_SIZE;
+         break;
+      }
       default:
          v3dv_debug_ignored_stype(ext->sType);
          break;
@@ -1586,8 +1610,7 @@ device_alloc(struct v3dv_device *device,
              VkDeviceSize size)
 {
    /* Our kernel interface is 32-bit */
-   if (size > UINT32_MAX)
-      return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+   assert(size <= UINT32_MAX);
 
    mem->bo = v3dv_bo_alloc(device, size, "device_alloc", false);
    if (!mem->bo)
@@ -1828,20 +1851,28 @@ v3dv_AllocateMemory(VkDevice _device,
    }
 
    VkResult result = VK_SUCCESS;
-   if (wsi_info) {
-      result = device_alloc_for_wsi(device, pAllocator, mem,
-                                    pAllocateInfo->allocationSize);
-   } else if (fd_info && fd_info->handleType) {
-      assert(fd_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
-             fd_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
-      result = device_import_bo(device, pAllocator,
-                                fd_info->fd, pAllocateInfo->allocationSize,
-                                &mem->bo);
-      mem->has_bo_ownership = false;
-      if (result == VK_SUCCESS)
-         close(fd_info->fd);
+
+   /* We always allocate device memory in multiples of a page, so round up
+    * requested size to that.
+    */
+   VkDeviceSize alloc_size = ALIGN(pAllocateInfo->allocationSize, 4096);
+
+   if (unlikely(alloc_size > MAX_MEMORY_ALLOCATION_SIZE)) {
+      result = VK_ERROR_OUT_OF_DEVICE_MEMORY;
    } else {
-      result = device_alloc(device, mem, pAllocateInfo->allocationSize);
+      if (wsi_info) {
+         result = device_alloc_for_wsi(device, pAllocator, mem, alloc_size);
+      } else if (fd_info && fd_info->handleType) {
+         assert(fd_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
+                fd_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
+         result = device_import_bo(device, pAllocator,
+                                   fd_info->fd, alloc_size, &mem->bo);
+         mem->has_bo_ownership = false;
+         if (result == VK_SUCCESS)
+            close(fd_info->fd);
+      } else {
+         result = device_alloc(device, mem, alloc_size);
+      }
    }
 
    if (result != VK_SUCCESS) {
index 852febe..90a1420 100644 (file)
@@ -124,6 +124,9 @@ struct v3dv_instance;
 
 struct v3d_simulator_file;
 
+/* Minimum required by the Vulkan 1.1 spec */
+#define MAX_MEMORY_ALLOCATION_SIZE (1ull << 30)
+
 struct v3dv_physical_device {
    struct vk_physical_device vk;
 
@@ -1516,6 +1519,8 @@ struct v3dv_descriptor_set {
    struct v3dv_descriptor descriptors[0];
 };
 
+uint32_t v3dv_max_descriptor_bo_size(void);
+
 struct v3dv_descriptor_set_binding_layout {
    VkDescriptorType type;