xref: /aosp_15_r20/external/skia/src/gpu/graphite/vk/VulkanDescriptorPool.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2 * Copyright 2023 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7 
8 #include "src/gpu/graphite/vk/VulkanDescriptorPool.h"
9 
10 #include "include/private/base/SkTArray.h"
11 #include "src/gpu/graphite/vk/VulkanSharedContext.h"
12 
13 namespace skgpu::graphite {
14 
Make(const VulkanSharedContext * context,SkSpan<DescriptorData> requestedDescCounts,VkDescriptorSetLayout layout)15 sk_sp<VulkanDescriptorPool> VulkanDescriptorPool::Make(const VulkanSharedContext* context,
16                                                        SkSpan<DescriptorData> requestedDescCounts,
17                                                        VkDescriptorSetLayout layout) {
18 
19     if (requestedDescCounts.empty()) {
20         return nullptr;
21     }
22 
23     // For each requested descriptor type and count, create a VkDescriptorPoolSize struct which
24     // specifies the descriptor type and quantity for pool creation. Multiple pool size structures
25     // may contain the same descriptor type - the pool will be created with enough storage for the
26     // total number of descriptors of each type. Source:
27     // https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VkDescriptorPoolSize
28     // Note: The kMaxNumDescriptors limit could be evaded since we do not currently track and check
29     // the cumulative quantities of each type of descriptor, but this is an internal call and it is
30     // highly unexpected for us to exceed this limit in practice.
31     skia_private::STArray<kDescriptorTypeCount, VkDescriptorPoolSize> poolSizes;
32     for (size_t i = 0; i < requestedDescCounts.size(); i++) {
33         SkASSERT(requestedDescCounts[i].fCount > 0);
34         if (requestedDescCounts[i].fCount > kMaxNumDescriptors) {
35             SkDebugf("The number of descriptors requested, %u, exceeds the maximum allowed (%d).\n",
36                      requestedDescCounts[i].fCount,
37                      kMaxNumDescriptors);
38             return nullptr;
39         }
40         VkDescriptorPoolSize& poolSize = poolSizes.push_back();
41         memset(&poolSize, 0, sizeof(VkDescriptorPoolSize));
42         // Map each DescriptorSetType to the appropriate backend VkDescriptorType
43         poolSize.type = DsTypeEnumToVkDs(requestedDescCounts[i].fType);
44         // Create a pool large enough to accommodate the maximum possible number of descriptor sets
45         poolSize.descriptorCount = requestedDescCounts[i].fCount * kMaxNumSets;
46     }
47 
48     VkDescriptorPoolCreateInfo createInfo;
49     memset(&createInfo, 0, sizeof(VkDescriptorPoolCreateInfo));
50     createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
51     createInfo.pNext = nullptr;
52     createInfo.flags = 0;
53     createInfo.maxSets = kMaxNumSets;
54     createInfo.poolSizeCount = requestedDescCounts.size();
55     createInfo.pPoolSizes = &poolSizes.front();
56 
57     VkDescriptorPool pool;
58     VkResult result;
59     VULKAN_CALL_RESULT(context,
60                        result,
61                        CreateDescriptorPool(context->device(),
62                                             &createInfo,
63                                             /*const VkAllocationCallbacks*=*/nullptr,
64                                             &pool));
65     if (result != VK_SUCCESS) {
66         VULKAN_CALL(context->interface(),
67                     DestroyDescriptorSetLayout(context->device(), layout, nullptr));
68         return nullptr;
69     }
70     return sk_sp<VulkanDescriptorPool>(new VulkanDescriptorPool(context, pool, layout));
71 }
72 
VulkanDescriptorPool(const VulkanSharedContext * context,VkDescriptorPool pool,VkDescriptorSetLayout layout)73 VulkanDescriptorPool::VulkanDescriptorPool(const VulkanSharedContext* context,
74                                            VkDescriptorPool pool,
75                                            VkDescriptorSetLayout layout)
76         : fSharedContext(context)
77         , fDescPool(pool)
78         , fDescSetLayout(layout) {}
79 
~VulkanDescriptorPool()80 VulkanDescriptorPool::~VulkanDescriptorPool() {
81     // Destroying the VkDescriptorPool will automatically free and delete any VkDescriptorSets
82     // allocated from the pool.
83     VULKAN_CALL(fSharedContext->interface(),
84                 DestroyDescriptorPool(fSharedContext->device(), fDescPool, nullptr));
85     if (fDescSetLayout != VK_NULL_HANDLE) {
86         VULKAN_CALL(fSharedContext->interface(),
87                     DestroyDescriptorSetLayout(fSharedContext->device(), fDescSetLayout, nullptr));
88         fDescSetLayout = VK_NULL_HANDLE;
89     }
90 }
91 
92 } // namespace skgpu::graphite
93