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,uint32_t descriptorCount,VkShaderStageFlags stageFlags,const VkSampler * pImmutableSamplers)37 DescriptorSetLayoutBuilder &DescriptorSetLayoutBuilder::addBinding(VkDescriptorType descriptorType,
38 uint32_t descriptorCount,
39 VkShaderStageFlags stageFlags,
40 const VkSampler *pImmutableSamplers)
41 {
42 if (pImmutableSamplers)
43 {
44 const ImmutableSamplerInfo immutableSamplerInfo = {(uint32_t)m_bindings.size(),
45 (uint32_t)m_immutableSamplers.size()};
46
47 m_immutableSamplerInfos.push_back(immutableSamplerInfo);
48
49 for (size_t descriptorNdx = 0; descriptorNdx < descriptorCount; descriptorNdx++)
50 m_immutableSamplers.push_back(pImmutableSamplers[descriptorNdx]);
51 }
52
53 // pImmutableSamplers will be updated at build time
54 const VkDescriptorSetLayoutBinding binding = {
55 (uint32_t)m_bindings.size(), // binding
56 descriptorType, // descriptorType
57 descriptorCount, // descriptorCount
58 stageFlags, // stageFlags
59 DE_NULL, // pImmutableSamplers
60 };
61 m_bindings.push_back(binding);
62 return *this;
63 }
64
addIndexedBinding(VkDescriptorType descriptorType,uint32_t descriptorCount,VkShaderStageFlags stageFlags,uint32_t dstBinding,const VkSampler * pImmutableSamplers)65 DescriptorSetLayoutBuilder &DescriptorSetLayoutBuilder::addIndexedBinding(VkDescriptorType descriptorType,
66 uint32_t descriptorCount,
67 VkShaderStageFlags stageFlags,
68 uint32_t dstBinding,
69 const VkSampler *pImmutableSamplers)
70 {
71 if (pImmutableSamplers)
72 {
73 const ImmutableSamplerInfo immutableSamplerInfo = {(uint32_t)dstBinding, (uint32_t)m_immutableSamplers.size()};
74
75 m_immutableSamplerInfos.push_back(immutableSamplerInfo);
76
77 for (size_t descriptorNdx = 0; descriptorNdx < descriptorCount; descriptorNdx++)
78 m_immutableSamplers.push_back(pImmutableSamplers[descriptorNdx]);
79 }
80
81 // pImmutableSamplers will be updated at build time
82 const VkDescriptorSetLayoutBinding binding = {
83 dstBinding, // binding
84 descriptorType, // descriptorType
85 descriptorCount, // descriptorCount
86 stageFlags, // stageFlags
87 DE_NULL, // pImmutableSamplers
88 };
89 m_bindings.push_back(binding);
90 return *this;
91 }
92
build(const DeviceInterface & vk,VkDevice device,VkDescriptorSetLayoutCreateFlags extraFlags) const93 Move<VkDescriptorSetLayout> DescriptorSetLayoutBuilder::build(const DeviceInterface &vk, VkDevice device,
94 VkDescriptorSetLayoutCreateFlags extraFlags) const
95 {
96 // Create new layout bindings with pImmutableSamplers updated
97 std::vector<VkDescriptorSetLayoutBinding> bindings = m_bindings;
98
99 for (size_t samplerInfoNdx = 0; samplerInfoNdx < m_immutableSamplerInfos.size(); samplerInfoNdx++)
100 {
101 const ImmutableSamplerInfo &samplerInfo = m_immutableSamplerInfos[samplerInfoNdx];
102 uint32_t bindingNdx = 0;
103
104 while (bindings[bindingNdx].binding != samplerInfo.bindingIndex)
105 {
106 bindingNdx++;
107
108 if (bindingNdx >= (uint32_t)bindings.size())
109 DE_FATAL("Immutable sampler not found");
110 }
111
112 bindings[bindingNdx].pImmutableSamplers = &m_immutableSamplers[samplerInfo.samplerBaseIndex];
113 }
114
115 const VkDescriptorSetLayoutCreateInfo createInfo = {
116 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
117 DE_NULL,
118 (VkDescriptorSetLayoutCreateFlags)extraFlags, // flags
119 (uint32_t)bindings.size(), // bindingCount
120 (bindings.empty()) ? (DE_NULL) : (&bindings.front()), // pBinding
121 };
122
123 return createDescriptorSetLayout(vk, device, &createInfo);
124 }
125
126 // DescriptorPoolBuilder
127
DescriptorPoolBuilder(void)128 DescriptorPoolBuilder::DescriptorPoolBuilder(void)
129 {
130 }
131
addType(VkDescriptorType type,uint32_t numDescriptors)132 DescriptorPoolBuilder &DescriptorPoolBuilder::addType(VkDescriptorType type, uint32_t numDescriptors)
133 {
134 if (numDescriptors == 0u)
135 {
136 // nothing to do
137 return *this;
138 }
139 else
140 {
141 for (size_t ndx = 0; ndx < m_counts.size(); ++ndx)
142 {
143 if (m_counts[ndx].type == type)
144 {
145 // augment existing requirement
146 m_counts[ndx].descriptorCount += numDescriptors;
147 return *this;
148 }
149 }
150
151 {
152 // new requirement
153 const VkDescriptorPoolSize typeCount = {
154 type, // type
155 numDescriptors, // numDescriptors
156 };
157
158 m_counts.push_back(typeCount);
159 return *this;
160 }
161 }
162 }
163
build(const DeviceInterface & vk,VkDevice device,VkDescriptorPoolCreateFlags flags,uint32_t maxSets,const void * pNext) const164 Move<VkDescriptorPool> DescriptorPoolBuilder::build(const DeviceInterface &vk, VkDevice device,
165 VkDescriptorPoolCreateFlags flags, uint32_t maxSets,
166 const void *pNext) const
167 {
168 const VkDescriptorPoolSize *const typeCountPtr = (m_counts.empty()) ? (DE_NULL) : (&m_counts[0]);
169 const VkDescriptorPoolCreateInfo createInfo = {
170 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
171 pNext,
172 flags,
173 maxSets,
174 (uint32_t)m_counts.size(), // poolSizeCount
175 typeCountPtr, // pPoolSizes
176 };
177
178 return createDescriptorPool(vk, device, &createInfo);
179 }
180
181 // DescriptorSetUpdateBuilder
182
DescriptorSetUpdateBuilder(void)183 DescriptorSetUpdateBuilder::DescriptorSetUpdateBuilder(void)
184 {
185 }
186
write(VkDescriptorSet destSet,uint32_t destBinding,uint32_t destArrayElement,uint32_t count,VkDescriptorType descriptorType,const VkDescriptorImageInfo * pImageInfo,const VkDescriptorBufferInfo * pBufferInfo,const VkBufferView * pTexelBufferView,const void * pNext)187 DescriptorSetUpdateBuilder &DescriptorSetUpdateBuilder::write(VkDescriptorSet destSet, uint32_t destBinding,
188 uint32_t destArrayElement, uint32_t count,
189 VkDescriptorType descriptorType,
190 const VkDescriptorImageInfo *pImageInfo,
191 const VkDescriptorBufferInfo *pBufferInfo,
192 const VkBufferView *pTexelBufferView, const void *pNext)
193 {
194 // pImageInfo, pBufferInfo and pTexelBufferView will be updated when calling update()
195 const VkWriteDescriptorSet writeParams = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
196 pNext,
197 destSet, //!< destSet
198 destBinding, //!< destBinding
199 destArrayElement, //!< destArrayElement
200 count, //!< count
201 descriptorType, //!< descriptorType
202 DE_NULL,
203 DE_NULL,
204 DE_NULL};
205
206 m_writes.push_back(writeParams);
207
208 // Store a copy of pImageInfo, pBufferInfo and pTexelBufferView
209 WriteDescriptorInfo writeInfo;
210
211 if (pImageInfo)
212 writeInfo.imageInfos.insert(writeInfo.imageInfos.end(), pImageInfo, pImageInfo + count);
213
214 if (pBufferInfo)
215 writeInfo.bufferInfos.insert(writeInfo.bufferInfos.end(), pBufferInfo, pBufferInfo + count);
216
217 if (pTexelBufferView)
218 writeInfo.texelBufferViews.insert(writeInfo.texelBufferViews.end(), pTexelBufferView, pTexelBufferView + count);
219
220 m_writeDescriptorInfos.push_back(writeInfo);
221
222 return *this;
223 }
224
copy(VkDescriptorSet srcSet,uint32_t srcBinding,uint32_t srcArrayElement,VkDescriptorSet destSet,uint32_t destBinding,uint32_t destArrayElement,uint32_t count)225 DescriptorSetUpdateBuilder &DescriptorSetUpdateBuilder::copy(VkDescriptorSet srcSet, uint32_t srcBinding,
226 uint32_t srcArrayElement, VkDescriptorSet destSet,
227 uint32_t destBinding, uint32_t destArrayElement,
228 uint32_t count)
229 {
230 const VkCopyDescriptorSet copyParams = {
231 VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET,
232 DE_NULL,
233 srcSet, //!< srcSet
234 srcBinding, //!< srcBinding
235 srcArrayElement, //!< srcArrayElement
236 destSet, //!< destSet
237 destBinding, //!< destBinding
238 destArrayElement, //!< destArrayElement
239 count, //!< count
240 };
241 m_copies.push_back(copyParams);
242 return *this;
243 }
244
update(const DeviceInterface & vk,VkDevice device) const245 void DescriptorSetUpdateBuilder::update(const DeviceInterface &vk, VkDevice device) const
246 {
247 // Update VkWriteDescriptorSet structures with stored info
248 std::vector<VkWriteDescriptorSet> writes = m_writes;
249
250 for (size_t writeNdx = 0; writeNdx < m_writes.size(); writeNdx++)
251 {
252 const WriteDescriptorInfo &writeInfo = m_writeDescriptorInfos[writeNdx];
253
254 if (!writeInfo.imageInfos.empty())
255 writes[writeNdx].pImageInfo = &writeInfo.imageInfos[0];
256
257 if (!writeInfo.bufferInfos.empty())
258 writes[writeNdx].pBufferInfo = &writeInfo.bufferInfos[0];
259
260 if (!writeInfo.texelBufferViews.empty())
261 writes[writeNdx].pTexelBufferView = &writeInfo.texelBufferViews[0];
262 }
263
264 const VkWriteDescriptorSet *const writePtr = (m_writes.empty()) ? (DE_NULL) : (&writes[0]);
265 const VkCopyDescriptorSet *const copyPtr = (m_copies.empty()) ? (DE_NULL) : (&m_copies[0]);
266
267 vk.updateDescriptorSets(device, (uint32_t)writes.size(), writePtr, (uint32_t)m_copies.size(), copyPtr);
268 }
269
270 #ifndef CTS_USES_VULKANSC
271
updateWithPush(const DeviceInterface & vk,VkCommandBuffer cmd,VkPipelineBindPoint bindPoint,VkPipelineLayout pipelineLayout,uint32_t setIdx,uint32_t descriptorIdx,uint32_t numDescriptors) const272 void DescriptorSetUpdateBuilder::updateWithPush(const DeviceInterface &vk, VkCommandBuffer cmd,
273 VkPipelineBindPoint bindPoint, VkPipelineLayout pipelineLayout,
274 uint32_t setIdx, uint32_t descriptorIdx, uint32_t numDescriptors) const
275 {
276 // Write all descriptors or just a subset?
277 uint32_t count = (numDescriptors) ? numDescriptors : (uint32_t)m_writes.size();
278
279 // Update VkWriteDescriptorSet structures with stored info
280 std::vector<VkWriteDescriptorSet> writes = m_writes;
281
282 for (size_t writeNdx = 0; writeNdx < m_writes.size(); writeNdx++)
283 {
284 const WriteDescriptorInfo &writeInfo = m_writeDescriptorInfos[writeNdx];
285
286 if (!writeInfo.imageInfos.empty())
287 writes[writeNdx].pImageInfo = &writeInfo.imageInfos[0];
288
289 if (!writeInfo.bufferInfos.empty())
290 writes[writeNdx].pBufferInfo = &writeInfo.bufferInfos[0];
291
292 if (!writeInfo.texelBufferViews.empty())
293 writes[writeNdx].pTexelBufferView = &writeInfo.texelBufferViews[0];
294 }
295
296 const VkWriteDescriptorSet *const writePtr = (m_writes.empty()) ? (DE_NULL) : (&writes[descriptorIdx]);
297
298 vk.cmdPushDescriptorSetKHR(cmd, bindPoint, pipelineLayout, setIdx, count, writePtr);
299 }
300
301 #endif // CTS_USES_VULKANSC
302
clear(void)303 void DescriptorSetUpdateBuilder::clear(void)
304 {
305 m_writeDescriptorInfos.clear();
306 m_writes.clear();
307 m_copies.clear();
308 }
309
310 } // namespace vk
311