1 /*
2 * Copyright 2016 Google Inc.
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 "GrVkDescriptorSetManager.h"
9
10 #include "GrVkDescriptorPool.h"
11 #include "GrVkDescriptorSet.h"
12 #include "GrVkGpu.h"
13 #include "GrVkUniformHandler.h"
14
GrVkDescriptorSetManager(GrVkGpu * gpu,VkDescriptorType type,const GrVkUniformHandler * uniformHandler)15 GrVkDescriptorSetManager::GrVkDescriptorSetManager(GrVkGpu* gpu,
16 VkDescriptorType type,
17 const GrVkUniformHandler* uniformHandler)
18 : fPoolManager(type, gpu, uniformHandler) {
19 if (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
20 SkASSERT(uniformHandler);
21 for (int i = 0; i < uniformHandler->numSamplers(); ++i) {
22 fBindingVisibilities.push_back(uniformHandler->samplerVisibility(i));
23 }
24 } else {
25 SkASSERT(type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
26 // We set the visibility of the first binding to the vertex shader and the second to the
27 // fragment shader.
28 fBindingVisibilities.push_back(kVertex_GrShaderFlag);
29 fBindingVisibilities.push_back(kFragment_GrShaderFlag);
30 }
31 }
32
GrVkDescriptorSetManager(GrVkGpu * gpu,VkDescriptorType type,const SkTArray<uint32_t> & visibilities)33 GrVkDescriptorSetManager::GrVkDescriptorSetManager(GrVkGpu* gpu,
34 VkDescriptorType type,
35 const SkTArray<uint32_t>& visibilities)
36 : fPoolManager(type, gpu, visibilities) {
37 if (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
38 for (int i = 0; i < visibilities.count(); ++i) {
39 fBindingVisibilities.push_back(visibilities[i]);
40 }
41 } else {
42 SkASSERT(type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
43 SkASSERT(2 == visibilities.count() &&
44 kVertex_GrShaderFlag == visibilities[0] &&
45 kFragment_GrShaderFlag == visibilities[1]);
46 // We set the visibility of the first binding to the vertex shader and the second to the
47 // fragment shader.
48 fBindingVisibilities.push_back(kVertex_GrShaderFlag);
49 fBindingVisibilities.push_back(kFragment_GrShaderFlag);
50 }
51 }
52
getDescriptorSet(GrVkGpu * gpu,const Handle & handle)53 const GrVkDescriptorSet* GrVkDescriptorSetManager::getDescriptorSet(GrVkGpu* gpu,
54 const Handle& handle) {
55 const GrVkDescriptorSet* ds = nullptr;
56 int count = fFreeSets.count();
57 if (count > 0) {
58 ds = fFreeSets[count - 1];
59 fFreeSets.removeShuffle(count - 1);
60 } else {
61 VkDescriptorSet vkDS;
62 fPoolManager.getNewDescriptorSet(gpu, &vkDS);
63
64 ds = new GrVkDescriptorSet(vkDS, fPoolManager.fPool, handle);
65 }
66 SkASSERT(ds);
67 return ds;
68 }
69
recycleDescriptorSet(const GrVkDescriptorSet * descSet)70 void GrVkDescriptorSetManager::recycleDescriptorSet(const GrVkDescriptorSet* descSet) {
71 SkASSERT(descSet);
72 fFreeSets.push_back(descSet);
73 }
74
release(const GrVkGpu * gpu)75 void GrVkDescriptorSetManager::release(const GrVkGpu* gpu) {
76 fPoolManager.freeGPUResources(gpu);
77
78 for (int i = 0; i < fFreeSets.count(); ++i) {
79 fFreeSets[i]->unref(gpu);
80 }
81 fFreeSets.reset();
82 }
83
abandon()84 void GrVkDescriptorSetManager::abandon() {
85 fPoolManager.abandonGPUResources();
86
87 for (int i = 0; i < fFreeSets.count(); ++i) {
88 fFreeSets[i]->unrefAndAbandon();
89 }
90 fFreeSets.reset();
91 }
92
isCompatible(VkDescriptorType type,const GrVkUniformHandler * uniHandler) const93 bool GrVkDescriptorSetManager::isCompatible(VkDescriptorType type,
94 const GrVkUniformHandler* uniHandler) const {
95 SkASSERT(uniHandler);
96 if (type != fPoolManager.fDescType) {
97 return false;
98 }
99
100 if (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
101 if (fBindingVisibilities.count() != uniHandler->numSamplers()) {
102 return false;
103 }
104 for (int i = 0; i < uniHandler->numSamplers(); ++i) {
105 if (uniHandler->samplerVisibility(i) != fBindingVisibilities[i]) {
106 return false;
107 }
108 }
109 }
110 return true;
111 }
112
isCompatible(VkDescriptorType type,const SkTArray<uint32_t> & visibilities) const113 bool GrVkDescriptorSetManager::isCompatible(VkDescriptorType type,
114 const SkTArray<uint32_t>& visibilities) const {
115 if (type != fPoolManager.fDescType) {
116 return false;
117 }
118
119 if (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
120 if (fBindingVisibilities.count() != visibilities.count()) {
121 return false;
122 }
123 for (int i = 0; i < visibilities.count(); ++i) {
124 if (visibilities[i] != fBindingVisibilities[i]) {
125 return false;
126 }
127 }
128 }
129 return true;
130 }
131
132 ////////////////////////////////////////////////////////////////////////////////
133
visibility_to_vk_stage_flags(uint32_t visibility)134 VkShaderStageFlags visibility_to_vk_stage_flags(uint32_t visibility) {
135 VkShaderStageFlags flags = 0;
136
137 if (visibility & kVertex_GrShaderFlag) {
138 flags |= VK_SHADER_STAGE_VERTEX_BIT;
139 }
140 if (visibility & kGeometry_GrShaderFlag) {
141 flags |= VK_SHADER_STAGE_GEOMETRY_BIT;
142 }
143 if (visibility & kFragment_GrShaderFlag) {
144 flags |= VK_SHADER_STAGE_FRAGMENT_BIT;
145 }
146 return flags;
147 }
148
DescriptorPoolManager(VkDescriptorType type,GrVkGpu * gpu,const GrVkUniformHandler * uniformHandler)149 GrVkDescriptorSetManager::DescriptorPoolManager::DescriptorPoolManager(
150 VkDescriptorType type,
151 GrVkGpu* gpu,
152 const GrVkUniformHandler* uniformHandler)
153 : fDescType(type)
154 , fCurrentDescriptorCount(0)
155 , fPool(nullptr) {
156 this->init(gpu, type, uniformHandler, nullptr);
157 }
158
DescriptorPoolManager(VkDescriptorType type,GrVkGpu * gpu,const SkTArray<uint32_t> & visibilities)159 GrVkDescriptorSetManager::DescriptorPoolManager::DescriptorPoolManager(
160 VkDescriptorType type,
161 GrVkGpu* gpu,
162 const SkTArray<uint32_t>& visibilities)
163 : fDescType(type)
164 , fCurrentDescriptorCount(0)
165 , fPool(nullptr) {
166 this->init(gpu, type, nullptr, &visibilities);
167 }
168
init(GrVkGpu * gpu,VkDescriptorType type,const GrVkUniformHandler * uniformHandler,const SkTArray<uint32_t> * visibilities)169 void GrVkDescriptorSetManager::DescriptorPoolManager::init(GrVkGpu* gpu,
170 VkDescriptorType type,
171 const GrVkUniformHandler* uniformHandler,
172 const SkTArray<uint32_t>* visibilities) {
173 if (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
174 SkASSERT(SkToBool(uniformHandler) != SkToBool(visibilities));
175 uint32_t numSamplers;
176 if (uniformHandler) {
177 numSamplers = (uint32_t)uniformHandler->numSamplers();
178 } else {
179 numSamplers = (uint32_t)visibilities->count();
180 }
181
182 std::unique_ptr<VkDescriptorSetLayoutBinding[]> dsSamplerBindings(
183 new VkDescriptorSetLayoutBinding[numSamplers]);
184 for (uint32_t i = 0; i < numSamplers; ++i) {
185 uint32_t visibility;
186 if (uniformHandler) {
187 visibility = uniformHandler->samplerVisibility(i);
188 } else {
189 visibility = (*visibilities)[i];
190 }
191 dsSamplerBindings[i].binding = i;
192 dsSamplerBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
193 dsSamplerBindings[i].descriptorCount = 1;
194 dsSamplerBindings[i].stageFlags = visibility_to_vk_stage_flags(visibility);
195 dsSamplerBindings[i].pImmutableSamplers = nullptr;
196 }
197
198 VkDescriptorSetLayoutCreateInfo dsSamplerLayoutCreateInfo;
199 memset(&dsSamplerLayoutCreateInfo, 0, sizeof(VkDescriptorSetLayoutCreateInfo));
200 dsSamplerLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
201 dsSamplerLayoutCreateInfo.pNext = nullptr;
202 dsSamplerLayoutCreateInfo.flags = 0;
203 dsSamplerLayoutCreateInfo.bindingCount = numSamplers;
204 // Setting to nullptr fixes an error in the param checker validation layer. Even though
205 // bindingCount is 0 (which is valid), it still tries to validate pBindings unless it is
206 // null.
207 dsSamplerLayoutCreateInfo.pBindings = numSamplers ? dsSamplerBindings.get() : nullptr;
208
209 GR_VK_CALL_ERRCHECK(gpu->vkInterface(),
210 CreateDescriptorSetLayout(gpu->device(),
211 &dsSamplerLayoutCreateInfo,
212 nullptr,
213 &fDescLayout));
214 fDescCountPerSet = numSamplers;
215 } else {
216 SkASSERT(type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
217 // Create Uniform Buffer Descriptor
218 // The vertex uniform buffer will have binding 0 and the fragment binding 1.
219 VkDescriptorSetLayoutBinding dsUniBindings[kUniformDescPerSet];
220 memset(&dsUniBindings, 0, 2 * sizeof(VkDescriptorSetLayoutBinding));
221 dsUniBindings[0].binding = GrVkUniformHandler::kVertexBinding;
222 dsUniBindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
223 dsUniBindings[0].descriptorCount = 1;
224 dsUniBindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
225 dsUniBindings[0].pImmutableSamplers = nullptr;
226 dsUniBindings[1].binding = GrVkUniformHandler::kFragBinding;
227 dsUniBindings[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
228 dsUniBindings[1].descriptorCount = 1;
229 dsUniBindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
230 dsUniBindings[1].pImmutableSamplers = nullptr;
231
232 VkDescriptorSetLayoutCreateInfo uniformLayoutCreateInfo;
233 memset(&uniformLayoutCreateInfo, 0, sizeof(VkDescriptorSetLayoutCreateInfo));
234 uniformLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
235 uniformLayoutCreateInfo.pNext = nullptr;
236 uniformLayoutCreateInfo.flags = 0;
237 uniformLayoutCreateInfo.bindingCount = 2;
238 uniformLayoutCreateInfo.pBindings = dsUniBindings;
239
240 GR_VK_CALL_ERRCHECK(gpu->vkInterface(), CreateDescriptorSetLayout(gpu->device(),
241 &uniformLayoutCreateInfo,
242 nullptr,
243 &fDescLayout));
244 fDescCountPerSet = kUniformDescPerSet;
245 }
246
247 SkASSERT(fDescCountPerSet < kStartNumDescriptors);
248 fMaxDescriptors = kStartNumDescriptors;
249 SkASSERT(fMaxDescriptors > 0);
250 this->getNewPool(gpu);
251 }
252
getNewPool(GrVkGpu * gpu)253 void GrVkDescriptorSetManager::DescriptorPoolManager::getNewPool(GrVkGpu* gpu) {
254 if (fPool) {
255 fPool->unref(gpu);
256 uint32_t newPoolSize = fMaxDescriptors + ((fMaxDescriptors + 1) >> 1);
257 if (newPoolSize < kMaxDescriptors) {
258 fMaxDescriptors = newPoolSize;
259 } else {
260 fMaxDescriptors = kMaxDescriptors;
261 }
262
263 }
264 fPool = gpu->resourceProvider().findOrCreateCompatibleDescriptorPool(fDescType,
265 fMaxDescriptors);
266 SkASSERT(fPool);
267 }
268
getNewDescriptorSet(GrVkGpu * gpu,VkDescriptorSet * ds)269 void GrVkDescriptorSetManager::DescriptorPoolManager::getNewDescriptorSet(GrVkGpu* gpu,
270 VkDescriptorSet* ds) {
271 if (!fMaxDescriptors) {
272 return;
273 }
274 fCurrentDescriptorCount += fDescCountPerSet;
275 if (fCurrentDescriptorCount > fMaxDescriptors) {
276 this->getNewPool(gpu);
277 fCurrentDescriptorCount = fDescCountPerSet;
278 }
279
280 VkDescriptorSetAllocateInfo dsAllocateInfo;
281 memset(&dsAllocateInfo, 0, sizeof(VkDescriptorSetAllocateInfo));
282 dsAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
283 dsAllocateInfo.pNext = nullptr;
284 dsAllocateInfo.descriptorPool = fPool->descPool();
285 dsAllocateInfo.descriptorSetCount = 1;
286 dsAllocateInfo.pSetLayouts = &fDescLayout;
287 GR_VK_CALL_ERRCHECK(gpu->vkInterface(), AllocateDescriptorSets(gpu->device(),
288 &dsAllocateInfo,
289 ds));
290 }
291
freeGPUResources(const GrVkGpu * gpu)292 void GrVkDescriptorSetManager::DescriptorPoolManager::freeGPUResources(const GrVkGpu* gpu) {
293 if (fDescLayout) {
294 GR_VK_CALL(gpu->vkInterface(), DestroyDescriptorSetLayout(gpu->device(), fDescLayout,
295 nullptr));
296 fDescLayout = VK_NULL_HANDLE;
297 }
298
299 if (fPool) {
300 fPool->unref(gpu);
301 fPool = nullptr;
302 }
303 }
304
abandonGPUResources()305 void GrVkDescriptorSetManager::DescriptorPoolManager::abandonGPUResources() {
306 fDescLayout = VK_NULL_HANDLE;
307 if (fPool) {
308 fPool->unrefAndAbandon();
309 fPool = nullptr;
310 }
311 }
312