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