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
28namespace vk
29{
30
31// DescriptorSetLayoutBuilder
32
33DescriptorSetLayoutBuilder::DescriptorSetLayoutBuilder (void)
34{
35}
36
37DescriptorSetLayoutBuilder& 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
69DescriptorSetLayoutBuilder& 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
102Move<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
111		bindings[samplerInfo.bindingIndex].pImmutableSamplers	= &m_immutableSamplers[samplerInfo.samplerBaseIndex];
112	}
113
114	const VkDescriptorSetLayoutCreateInfo		createInfo	=
115	{
116		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
117		DE_NULL,
118		(VkDescriptorSetLayoutCreateFlags)extraFlags,			// flags
119		(deUint32)bindings.size(),								// bindingCount
120		(bindings.empty()) ? (DE_NULL) : (bindings.data()),		// pBinding
121	};
122
123	return createDescriptorSetLayout(vk, device, &createInfo);
124}
125
126// DescriptorPoolBuilder
127
128DescriptorPoolBuilder::DescriptorPoolBuilder (void)
129{
130}
131
132DescriptorPoolBuilder& DescriptorPoolBuilder::addType (VkDescriptorType type, deUint32 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			{
155				type,			// type
156				numDescriptors,	// numDescriptors
157			};
158
159			m_counts.push_back(typeCount);
160			return *this;
161		}
162	}
163}
164
165Move<VkDescriptorPool> DescriptorPoolBuilder::build (const DeviceInterface& vk, VkDevice device, VkDescriptorPoolCreateFlags flags, deUint32 maxSets) const
166{
167	const VkDescriptorPoolSize* const	typeCountPtr	= (m_counts.empty()) ? (DE_NULL) : (&m_counts[0]);
168	const VkDescriptorPoolCreateInfo	createInfo		=
169	{
170		VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
171		DE_NULL,
172		flags,
173		maxSets,
174		(deUint32)m_counts.size(),		// poolSizeCount
175		typeCountPtr,					// pPoolSizes
176	};
177
178	return createDescriptorPool(vk, device, &createInfo);
179}
180
181// DescriptorSetUpdateBuilder
182
183DescriptorSetUpdateBuilder::DescriptorSetUpdateBuilder (void)
184{
185}
186
187DescriptorSetUpdateBuilder& DescriptorSetUpdateBuilder::write (VkDescriptorSet					destSet,
188															   deUint32							destBinding,
189															   deUint32							destArrayElement,
190															   deUint32							count,
191															   VkDescriptorType					descriptorType,
192															   const VkDescriptorImageInfo*		pImageInfo,
193															   const VkDescriptorBufferInfo*	pBufferInfo,
194															   const VkBufferView*				pTexelBufferView)
195{
196	// pImageInfo, pBufferInfo and pTexelBufferView will be updated when calling update()
197	const VkWriteDescriptorSet writeParams =
198	{
199		VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
200		DE_NULL,
201		destSet,			//!< destSet
202		destBinding,		//!< destBinding
203		destArrayElement,	//!< destArrayElement
204		count,				//!< count
205		descriptorType,		//!< descriptorType
206		DE_NULL,
207		DE_NULL,
208		DE_NULL
209	};
210
211	m_writes.push_back(writeParams);
212
213	// Store a copy of pImageInfo, pBufferInfo and pTexelBufferView
214	WriteDescriptorInfo	writeInfo;
215
216	if (pImageInfo)
217		writeInfo.imageInfos.insert(writeInfo.imageInfos.end(), pImageInfo, pImageInfo + count);
218
219	if (pBufferInfo)
220		writeInfo.bufferInfos.insert(writeInfo.bufferInfos.end(), pBufferInfo, pBufferInfo + count);
221
222	if (pTexelBufferView)
223		writeInfo.texelBufferViews.insert(writeInfo.texelBufferViews.end(), pTexelBufferView, pTexelBufferView + count);
224
225	m_writeDescriptorInfos.push_back(writeInfo);
226
227	return *this;
228}
229
230DescriptorSetUpdateBuilder& DescriptorSetUpdateBuilder::copy (VkDescriptorSet	srcSet,
231															  deUint32			srcBinding,
232															  deUint32			srcArrayElement,
233															  VkDescriptorSet	destSet,
234															  deUint32			destBinding,
235															  deUint32			destArrayElement,
236															  deUint32			count)
237{
238	const VkCopyDescriptorSet copyParams =
239	{
240		VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET,
241		DE_NULL,
242		srcSet,				//!< srcSet
243		srcBinding,			//!< srcBinding
244		srcArrayElement,	//!< srcArrayElement
245		destSet,			//!< destSet
246		destBinding,		//!< destBinding
247		destArrayElement,	//!< destArrayElement
248		count,				//!< count
249	};
250	m_copies.push_back(copyParams);
251	return *this;
252}
253
254void DescriptorSetUpdateBuilder::update (const DeviceInterface& vk, VkDevice device) const
255{
256	// Update VkWriteDescriptorSet structures with stored info
257	std::vector<VkWriteDescriptorSet> writes	= m_writes;
258
259	for (size_t writeNdx = 0; writeNdx < m_writes.size(); writeNdx++)
260	{
261		const WriteDescriptorInfo& writeInfo = m_writeDescriptorInfos[writeNdx];
262
263		if (!writeInfo.imageInfos.empty())
264			writes[writeNdx].pImageInfo			= &writeInfo.imageInfos[0];
265
266		if (!writeInfo.bufferInfos.empty())
267			writes[writeNdx].pBufferInfo		= &writeInfo.bufferInfos[0];
268
269		if (!writeInfo.texelBufferViews.empty())
270			writes[writeNdx].pTexelBufferView	= &writeInfo.texelBufferViews[0];
271	}
272
273	const VkWriteDescriptorSet* const	writePtr	= (m_writes.empty()) ? (DE_NULL) : (&writes[0]);
274	const VkCopyDescriptorSet* const	copyPtr		= (m_copies.empty()) ? (DE_NULL) : (&m_copies[0]);
275
276	vk.updateDescriptorSets(device, (deUint32)writes.size(), writePtr, (deUint32)m_copies.size(), copyPtr);
277}
278
279void DescriptorSetUpdateBuilder::updateWithPush (const DeviceInterface& vk, VkCommandBuffer cmd, VkPipelineBindPoint bindPoint, VkPipelineLayout pipelineLayout, deUint32 setIdx) const
280{
281	// Update VkWriteDescriptorSet structures with stored info
282	std::vector<VkWriteDescriptorSet> writes	= m_writes;
283
284	for (size_t writeNdx = 0; writeNdx < m_writes.size(); writeNdx++)
285	{
286		const WriteDescriptorInfo& writeInfo = m_writeDescriptorInfos[writeNdx];
287
288		if (!writeInfo.imageInfos.empty())
289			writes[writeNdx].pImageInfo			= &writeInfo.imageInfos[0];
290
291		if (!writeInfo.bufferInfos.empty())
292			writes[writeNdx].pBufferInfo		= &writeInfo.bufferInfos[0];
293
294		if (!writeInfo.texelBufferViews.empty())
295			writes[writeNdx].pTexelBufferView	= &writeInfo.texelBufferViews[0];
296	}
297
298	const VkWriteDescriptorSet* const	writePtr	= (m_writes.empty()) ? (DE_NULL) : (&writes[0]);
299
300	vk.cmdPushDescriptorSetKHR(cmd, bindPoint, pipelineLayout, setIdx, (deUint32)m_writes.size(), writePtr);
301}
302
303} // vk
304