1 /*-------------------------------------------------------------------------
2 * Vulkan CTS Framework
3 * --------------------
4 *
5 * Copyright (c) 2015 Google Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Vulkan object builder utilities.
22 *//*--------------------------------------------------------------------*/
23
24 #include "vkBuilderUtil.hpp"
25
26 #include "vkRefUtil.hpp"
27
28 namespace vk
29 {
30
31 // DescriptorSetLayoutBuilder
32
DescriptorSetLayoutBuilder(void)33 DescriptorSetLayoutBuilder::DescriptorSetLayoutBuilder (void)
34 {
35 }
36
addBinding(VkDescriptorType descriptorType,deUint32 descriptorCount,VkShaderStageFlags stageFlags,const VkSampler * pImmutableSamplers)37 DescriptorSetLayoutBuilder& DescriptorSetLayoutBuilder::addBinding (VkDescriptorType descriptorType,
38 deUint32 descriptorCount,
39 VkShaderStageFlags stageFlags,
40 const VkSampler* pImmutableSamplers)
41 {
42 if (pImmutableSamplers)
43 {
44 const ImmutableSamplerInfo immutableSamplerInfo =
45 {
46 (deUint32)m_bindings.size(),
47 (deUint32)m_immutableSamplers.size()
48 };
49
50 m_immutableSamplerInfos.push_back(immutableSamplerInfo);
51
52 for (size_t descriptorNdx = 0; descriptorNdx < descriptorCount; descriptorNdx++)
53 m_immutableSamplers.push_back(pImmutableSamplers[descriptorNdx]);
54 }
55
56 // pImmutableSamplers will be updated at build time
57 const VkDescriptorSetLayoutBinding binding =
58 {
59 (deUint32)m_bindings.size(), // binding
60 descriptorType, // descriptorType
61 descriptorCount, // descriptorCount
62 stageFlags, // stageFlags
63 DE_NULL, // pImmutableSamplers
64 };
65 m_bindings.push_back(binding);
66 return *this;
67 }
68
addIndexedBinding(VkDescriptorType descriptorType,deUint32 descriptorCount,VkShaderStageFlags stageFlags,deUint32 dstBinding,const VkSampler * pImmutableSamplers)69 DescriptorSetLayoutBuilder& DescriptorSetLayoutBuilder::addIndexedBinding (VkDescriptorType descriptorType,
70 deUint32 descriptorCount,
71 VkShaderStageFlags stageFlags,
72 deUint32 dstBinding,
73 const VkSampler* pImmutableSamplers)
74 {
75 if (pImmutableSamplers)
76 {
77 const ImmutableSamplerInfo immutableSamplerInfo =
78 {
79 (deUint32)dstBinding,
80 (deUint32)m_immutableSamplers.size()
81 };
82
83 m_immutableSamplerInfos.push_back(immutableSamplerInfo);
84
85 for (size_t descriptorNdx = 0; descriptorNdx < descriptorCount; descriptorNdx++)
86 m_immutableSamplers.push_back(pImmutableSamplers[descriptorNdx]);
87 }
88
89 // pImmutableSamplers will be updated at build time
90 const VkDescriptorSetLayoutBinding binding =
91 {
92 dstBinding, // binding
93 descriptorType, // descriptorType
94 descriptorCount, // descriptorCount
95 stageFlags, // stageFlags
96 DE_NULL, // pImmutableSamplers
97 };
98 m_bindings.push_back(binding);
99 return *this;
100 }
101
build(const DeviceInterface & vk,VkDevice device,VkDescriptorSetLayoutCreateFlags extraFlags) const102 Move<VkDescriptorSetLayout> DescriptorSetLayoutBuilder::build (const DeviceInterface& vk, VkDevice device, VkDescriptorSetLayoutCreateFlags extraFlags) const
103 {
104 // Create new layout bindings with pImmutableSamplers updated
105 std::vector<VkDescriptorSetLayoutBinding> bindings = m_bindings;
106
107 for (size_t samplerInfoNdx = 0; samplerInfoNdx < m_immutableSamplerInfos.size(); samplerInfoNdx++)
108 {
109 const ImmutableSamplerInfo& samplerInfo = m_immutableSamplerInfos[samplerInfoNdx];
110 deUint32 bindingNdx = 0;
111
112 while (bindings[bindingNdx].binding != samplerInfo.bindingIndex)
113 {
114 bindingNdx++;
115
116 if (bindingNdx >= (deUint32)bindings.size())
117 DE_FATAL("Immutable sampler not found");
118 }
119
120 bindings[bindingNdx].pImmutableSamplers = &m_immutableSamplers[samplerInfo.samplerBaseIndex];
121 }
122
123 const VkDescriptorSetLayoutCreateInfo createInfo =
124 {
125 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
126 DE_NULL,
127 (VkDescriptorSetLayoutCreateFlags)extraFlags, // flags
128 (deUint32)bindings.size(), // bindingCount
129 (bindings.empty()) ? (DE_NULL) : (&bindings.front()), // pBinding
130 };
131
132 return createDescriptorSetLayout(vk, device, &createInfo);
133 }
134
135 // DescriptorPoolBuilder
136
DescriptorPoolBuilder(void)137 DescriptorPoolBuilder::DescriptorPoolBuilder (void)
138 {
139 }
140
addType(VkDescriptorType type,deUint32 numDescriptors)141 DescriptorPoolBuilder& DescriptorPoolBuilder::addType (VkDescriptorType type, deUint32 numDescriptors)
142 {
143 if (numDescriptors == 0u)
144 {
145 // nothing to do
146 return *this;
147 }
148 else
149 {
150 for (size_t ndx = 0; ndx < m_counts.size(); ++ndx)
151 {
152 if (m_counts[ndx].type == type)
153 {
154 // augment existing requirement
155 m_counts[ndx].descriptorCount += numDescriptors;
156 return *this;
157 }
158 }
159
160 {
161 // new requirement
162 const VkDescriptorPoolSize typeCount =
163 {
164 type, // type
165 numDescriptors, // numDescriptors
166 };
167
168 m_counts.push_back(typeCount);
169 return *this;
170 }
171 }
172 }
173
build(const DeviceInterface & vk,VkDevice device,VkDescriptorPoolCreateFlags flags,deUint32 maxSets,const void * pNext) const174 Move<VkDescriptorPool> DescriptorPoolBuilder::build (const DeviceInterface& vk, VkDevice device, VkDescriptorPoolCreateFlags flags, deUint32 maxSets, const void *pNext) const
175 {
176 const VkDescriptorPoolSize* const typeCountPtr = (m_counts.empty()) ? (DE_NULL) : (&m_counts[0]);
177 const VkDescriptorPoolCreateInfo createInfo =
178 {
179 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
180 pNext,
181 flags,
182 maxSets,
183 (deUint32)m_counts.size(), // poolSizeCount
184 typeCountPtr, // pPoolSizes
185 };
186
187 return createDescriptorPool(vk, device, &createInfo);
188 }
189
190 // DescriptorSetUpdateBuilder
191
DescriptorSetUpdateBuilder(void)192 DescriptorSetUpdateBuilder::DescriptorSetUpdateBuilder (void)
193 {
194 }
195
write(VkDescriptorSet destSet,deUint32 destBinding,deUint32 destArrayElement,deUint32 count,VkDescriptorType descriptorType,const VkDescriptorImageInfo * pImageInfo,const VkDescriptorBufferInfo * pBufferInfo,const VkBufferView * pTexelBufferView,const void * pNext)196 DescriptorSetUpdateBuilder& DescriptorSetUpdateBuilder::write (VkDescriptorSet destSet,
197 deUint32 destBinding,
198 deUint32 destArrayElement,
199 deUint32 count,
200 VkDescriptorType descriptorType,
201 const VkDescriptorImageInfo* pImageInfo,
202 const VkDescriptorBufferInfo* pBufferInfo,
203 const VkBufferView* pTexelBufferView,
204 const void* pNext)
205 {
206 // pImageInfo, pBufferInfo and pTexelBufferView will be updated when calling update()
207 const VkWriteDescriptorSet writeParams =
208 {
209 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
210 pNext,
211 destSet, //!< destSet
212 destBinding, //!< destBinding
213 destArrayElement, //!< destArrayElement
214 count, //!< count
215 descriptorType, //!< descriptorType
216 DE_NULL,
217 DE_NULL,
218 DE_NULL
219 };
220
221 m_writes.push_back(writeParams);
222
223 // Store a copy of pImageInfo, pBufferInfo and pTexelBufferView
224 WriteDescriptorInfo writeInfo;
225
226 if (pImageInfo)
227 writeInfo.imageInfos.insert(writeInfo.imageInfos.end(), pImageInfo, pImageInfo + count);
228
229 if (pBufferInfo)
230 writeInfo.bufferInfos.insert(writeInfo.bufferInfos.end(), pBufferInfo, pBufferInfo + count);
231
232 if (pTexelBufferView)
233 writeInfo.texelBufferViews.insert(writeInfo.texelBufferViews.end(), pTexelBufferView, pTexelBufferView + count);
234
235 m_writeDescriptorInfos.push_back(writeInfo);
236
237 return *this;
238 }
239
copy(VkDescriptorSet srcSet,deUint32 srcBinding,deUint32 srcArrayElement,VkDescriptorSet destSet,deUint32 destBinding,deUint32 destArrayElement,deUint32 count)240 DescriptorSetUpdateBuilder& DescriptorSetUpdateBuilder::copy (VkDescriptorSet srcSet,
241 deUint32 srcBinding,
242 deUint32 srcArrayElement,
243 VkDescriptorSet destSet,
244 deUint32 destBinding,
245 deUint32 destArrayElement,
246 deUint32 count)
247 {
248 const VkCopyDescriptorSet copyParams =
249 {
250 VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET,
251 DE_NULL,
252 srcSet, //!< srcSet
253 srcBinding, //!< srcBinding
254 srcArrayElement, //!< srcArrayElement
255 destSet, //!< destSet
256 destBinding, //!< destBinding
257 destArrayElement, //!< destArrayElement
258 count, //!< count
259 };
260 m_copies.push_back(copyParams);
261 return *this;
262 }
263
update(const DeviceInterface & vk,VkDevice device) const264 void DescriptorSetUpdateBuilder::update (const DeviceInterface& vk, VkDevice device) const
265 {
266 // Update VkWriteDescriptorSet structures with stored info
267 std::vector<VkWriteDescriptorSet> writes = m_writes;
268
269 for (size_t writeNdx = 0; writeNdx < m_writes.size(); writeNdx++)
270 {
271 const WriteDescriptorInfo& writeInfo = m_writeDescriptorInfos[writeNdx];
272
273 if (!writeInfo.imageInfos.empty())
274 writes[writeNdx].pImageInfo = &writeInfo.imageInfos[0];
275
276 if (!writeInfo.bufferInfos.empty())
277 writes[writeNdx].pBufferInfo = &writeInfo.bufferInfos[0];
278
279 if (!writeInfo.texelBufferViews.empty())
280 writes[writeNdx].pTexelBufferView = &writeInfo.texelBufferViews[0];
281 }
282
283 const VkWriteDescriptorSet* const writePtr = (m_writes.empty()) ? (DE_NULL) : (&writes[0]);
284 const VkCopyDescriptorSet* const copyPtr = (m_copies.empty()) ? (DE_NULL) : (&m_copies[0]);
285
286 vk.updateDescriptorSets(device, (deUint32)writes.size(), writePtr, (deUint32)m_copies.size(), copyPtr);
287 }
288
updateWithPush(const DeviceInterface & vk,VkCommandBuffer cmd,VkPipelineBindPoint bindPoint,VkPipelineLayout pipelineLayout,deUint32 setIdx,deUint32 descriptorIdx,deUint32 numDescriptors) const289 void DescriptorSetUpdateBuilder::updateWithPush (const DeviceInterface& vk, VkCommandBuffer cmd, VkPipelineBindPoint bindPoint, VkPipelineLayout pipelineLayout, deUint32 setIdx, deUint32 descriptorIdx, deUint32 numDescriptors) const
290 {
291 // Write all descriptors or just a subset?
292 deUint32 count = (numDescriptors) ? numDescriptors : (deUint32)m_writes.size();
293
294 // Update VkWriteDescriptorSet structures with stored info
295 std::vector<VkWriteDescriptorSet> writes = m_writes;
296
297 for (size_t writeNdx = 0; writeNdx < m_writes.size(); writeNdx++)
298 {
299 const WriteDescriptorInfo& writeInfo = m_writeDescriptorInfos[writeNdx];
300
301 if (!writeInfo.imageInfos.empty())
302 writes[writeNdx].pImageInfo = &writeInfo.imageInfos[0];
303
304 if (!writeInfo.bufferInfos.empty())
305 writes[writeNdx].pBufferInfo = &writeInfo.bufferInfos[0];
306
307 if (!writeInfo.texelBufferViews.empty())
308 writes[writeNdx].pTexelBufferView = &writeInfo.texelBufferViews[0];
309 }
310
311 const VkWriteDescriptorSet* const writePtr = (m_writes.empty()) ? (DE_NULL) : (&writes[descriptorIdx]);
312
313 vk.cmdPushDescriptorSetKHR(cmd, bindPoint, pipelineLayout, setIdx, count, writePtr);
314 }
315
clear(void)316 void DescriptorSetUpdateBuilder::clear(void)
317 {
318 m_writeDescriptorInfos.clear();
319 m_writes.clear();
320 m_copies.clear();
321 }
322
323 } // vk
324