1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2022 The Khronos Group Inc.
6  * Copyright (c) 2022 Google Inc.
7  * Copyright (c) 2023 LunarG, Inc.
8  * Copyright (c) 2023 Nintendo
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  *//*!
23  * \file vktPipelineDescriptorLimits.cpp
24  * \brief Descriptor limit tests
25  *//*--------------------------------------------------------------------*/
26 
27 #include "vktPipelineDescriptorLimitsTests.hpp"
28 #include "vktPipelineClearUtil.hpp"
29 
30 #include "vkBuilderUtil.hpp"
31 #include "vkCmdUtil.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkImageUtil.hpp"
34 #include "vkObjUtil.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkTypeUtil.hpp"
37 
38 #include "tcuImageCompare.hpp"
39 #include "tcuTestLog.hpp"
40 #include "tcuTextureUtil.hpp"
41 
42 #include "deUniquePtr.hpp"
43 
44 #include <array>
45 
46 namespace vkt
47 {
48 namespace pipeline
49 {
50 
51 using namespace vk;
52 
53 namespace
54 {
55 
56 enum class TestType
57 {
58 	Samplers			= 0,
59 	UniformBuffers		= 1,
60 	StorageBuffers		= 2,
61 	SampledImages		= 3,
62 	StorageImages		= 4,
63 	InputAttachments	= 5
64 };
65 
makeImageCreateInfo(const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage)66 inline VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage)
67 {
68 	const VkImageCreateInfo	imageParams	=
69 	{
70 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
71 		DE_NULL,								// const void*				pNext;
72 		(VkImageCreateFlags)0,					// VkImageCreateFlags		flags;
73 		VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
74 		format,									// VkFormat					format;
75 		makeExtent3D(size.x(), size.y(), 1),	// VkExtent3D				extent;
76 		1u,										// deUint32					mipLevels;
77 		1u,										// deUint32					arrayLayers;
78 		VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples;
79 		VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
80 		usage,									// VkImageUsageFlags		usage;
81 		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
82 		0u,										// deUint32					queueFamilyIndexCount;
83 		DE_NULL,								// const deUint32*			pQueueFamilyIndices;
84 		VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			initialLayout;
85 	};
86 	return imageParams;
87 }
88 
generateColorImage(const VkFormat format, const tcu::IVec2 &renderSize, const tcu::Vec4 color)89 tcu::TextureLevel generateColorImage (const VkFormat format, const tcu::IVec2 &renderSize, const tcu::Vec4 color)
90 {
91 	tcu::TextureLevel image(mapVkFormat(format), renderSize.x(), renderSize.y());
92 	tcu::clear(image.getAccess(), color);
93 
94 	return image;
95 }
96 
makeRenderPassInputAttachment(const DeviceInterface& vk, const VkDevice device, const PipelineConstructionType pipelineConstructionType, const VkFormat colorFormat)97 RenderPassWrapper makeRenderPassInputAttachment (const DeviceInterface&				vk,
98 												  const VkDevice					device,
99 												  const PipelineConstructionType	pipelineConstructionType,
100 												  const VkFormat					colorFormat)
101 {
102 	const VkAttachmentDescription				colorAttachmentDescription	=
103 	{
104 		(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags	flags
105 		colorFormat,								// VkFormat						format
106 		VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits		samples
107 		VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp			loadOp
108 		VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp			storeOp
109 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp			stencilLoadOp
110 		VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp			stencilStoreOp
111 		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout				initialLayout
112 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout				finalLayout
113 	};
114 
115 	const VkAttachmentDescription				inputAttachmentDescription	=
116 	{
117 		VkAttachmentDescriptionFlags(0),			// VkAttachmentDescriptionFlags	flags;
118 		colorFormat,								// VkFormat						format;
119 		VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits		samples;
120 		VK_ATTACHMENT_LOAD_OP_LOAD,					// VkAttachmentLoadOp			loadOp;
121 		VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp			storeOp;
122 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp			stencilLoadOp;
123 		VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp			stencilStoreOp;
124 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout				initialLayout;
125 		VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL	// VkImageLayout				finalLayout;
126 	};
127 
128 	const std::vector<VkAttachmentDescription>	attachmentDescriptions		= { inputAttachmentDescription, inputAttachmentDescription, colorAttachmentDescription };
129 
130 	const std::vector<VkAttachmentReference>	inputAttachmentReferences	= { { 0u, inputAttachmentDescription.finalLayout }, { 1u, inputAttachmentDescription.finalLayout } };
131 
132 	const VkAttachmentReference					colorAttachmentReference	= { 2u, colorAttachmentDescription.finalLayout };
133 
134 	const VkSubpassDescription					subpassDescription			=
135 	{
136 		(VkSubpassDescriptionFlags)0,								// VkSubpassDescriptionFlags	flags
137 		VK_PIPELINE_BIND_POINT_GRAPHICS,							// VkPipelineBindPoint			pipelineBindPoint
138 		static_cast<deUint32>(inputAttachmentReferences.size()),	// deUint32						inputAttachmentCount
139 		inputAttachmentReferences.data(),							// const VkAttachmentReference*	pInputAttachments
140 		1u,															// deUint32						colorAttachmentCount
141 		&colorAttachmentReference,									// const VkAttachmentReference*	pColorAttachments
142 		DE_NULL,													// const VkAttachmentReference*	pResolveAttachments
143 		DE_NULL,													// const VkAttachmentReference*	pDepthStencilAttachment
144 		0u,															// deUint32						preserveAttachmentCount
145 		DE_NULL														// const deUint32*				pPreserveAttachments
146 	};
147 
148 	const VkRenderPassCreateInfo				renderPassInfo				=
149 	{
150 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType					sType
151 		DE_NULL,									// const void*						pNext
152 		(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags
153 		(deUint32)attachmentDescriptions.size(),	// deUint32							attachmentCount
154 		attachmentDescriptions.data(),				// const VkAttachmentDescription*	pAttachments
155 		1u,											// deUint32							subpassCount
156 		&subpassDescription,						// const VkSubpassDescription*		pSubpasses
157 		0u,											// deUint32							dependencyCount
158 		DE_NULL										// const VkSubpassDependency*		pDependencies
159 	};
160 
161 	return RenderPassWrapper(pipelineConstructionType, vk, device, &renderPassInfo);
162 }
163 
164 struct TestParams
165 {
TestParamsvkt::pipeline::__anon28176::TestType::TestParams166 	TestParams	(const PipelineConstructionType	pipelineConstructionType,
167 				const TestType					testType,
168 				const bool						useCompShader,
169 				const tcu::IVec2				framebufferSize,
170 				const deUint32					descCount)
171 				: m_pipelineConstructionType	(pipelineConstructionType)
172 				, m_testType					(testType)
173 				, m_useCompShader				(useCompShader)
174 				, m_framebufferSize				(framebufferSize)
175 				, m_descCount					(descCount)
176 	{}
177 
178 	const PipelineConstructionType	m_pipelineConstructionType;
179 	const TestType					m_testType;
180 	const bool						m_useCompShader;
181 	const tcu::IVec2				m_framebufferSize;
182 	const deUint32					m_descCount;
183 
getDescCountvkt::pipeline::__anon28176::TestType::TestParams184 	deUint32 getDescCount() const
185 	{
186 		deUint32 descCnt = m_descCount;
187 
188 		if (m_testType == TestType::StorageBuffers && m_useCompShader)
189 			descCnt = m_descCount - 1u;
190 
191 		return descCnt;
192 	}
193 };
194 
195 class DescriptorLimitTestInstance : public vkt::TestInstance
196 {
197 public:
DescriptorLimitTestInstance(Context& context, const TestParams& params)198 							DescriptorLimitTestInstance		(Context&						context,
199 															const TestParams&				params)
200 															: vkt::TestInstance				(context)
201 															, m_params						(params)
202 							{}
203 
~DescriptorLimitTestInstance()204 							~DescriptorLimitTestInstance	()
205 							{}
206 
207 	virtual tcu::TestStatus	iterate							(void);
208 
209 private:
210 	struct BufferInfo
211 	{
212 		tcu::Vec4	color;
213 	};
214 	TestParams	m_params;
215 };
216 
iterate(void)217 tcu::TestStatus DescriptorLimitTestInstance::iterate (void)
218 {
219 	tcu::TestLog&							log										= m_context.getTestContext().getLog();
220 	const InstanceInterface&				vki										= m_context.getInstanceInterface();
221 	const DeviceInterface&					vk										= m_context.getDeviceInterface();
222 	const VkPhysicalDevice					physicalDevice							= m_context.getPhysicalDevice();
223 	const VkDevice							vkDevice								= m_context.getDevice();
224 	Allocator&								allocator								= m_context.getDefaultAllocator();
225 	const VkQueue							queue									= m_context.getUniversalQueue();
226 	const deUint32							queueFamilyIndex						= m_context.getUniversalQueueFamilyIndex();
227 	VkFormat								colorFormat								= VK_FORMAT_R8G8B8A8_UNORM;
228 
229 	// Pick correct test parameters based on test type
230 	const VkShaderStageFlags				shaderStageFlags						= m_params.m_useCompShader ? VkShaderStageFlags(VK_SHADER_STAGE_COMPUTE_BIT) : VkShaderStageFlags(VK_SHADER_STAGE_FRAGMENT_BIT);
231 	const VkPipelineStageFlags				pipelineStageFlags						= m_params.m_useCompShader ? VkPipelineStageFlags(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT) : VkPipelineStageFlags(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
232 
233 	const VkImageUsageFlags					imageFlags								= m_params.m_testType == TestType::InputAttachments
234 																					? VkImageUsageFlags(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)
235 																					: m_params.m_testType == TestType::StorageImages
236 																					? VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT
237 																					: VkImageUsageFlags(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
238 
239 	const VkImageLayout						finalImageLayout						= m_params.m_testType == TestType::InputAttachments
240 																					? VkImageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
241 																					: m_params.m_testType == TestType::StorageImages
242 																					? VkImageLayout(VK_IMAGE_LAYOUT_GENERAL)
243 																					: VkImageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
244 
245 	// Create shaders
246 	ShaderWrapper							vertexShaderModule						= ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("vert"), 0u);
247 	ShaderWrapper							testedShaderModule						= ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("test"), 0u);
248 
249 	// Create images
250 	const VkImageSubresourceRange			colorSubresourceRange					= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
251 	const Move<VkImage>						colorImage								(makeImage(vk, vkDevice, makeImageCreateInfo(m_params.m_framebufferSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
252 	const de::MovePtr<Allocation>			colorImageAlloc							(bindImage(vk, vkDevice, allocator, *colorImage, MemoryRequirement::Any));
253 	const Move<VkImageView>					colorImageView							(makeImageView(vk, vkDevice, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
254 
255 	const Move<VkImage>						inputImages[2]							{ (makeImage(vk, vkDevice, makeImageCreateInfo(m_params.m_framebufferSize, colorFormat, imageFlags)))
256 																					, (makeImage(vk, vkDevice, makeImageCreateInfo(m_params.m_framebufferSize, colorFormat, imageFlags))) };
257 	const de::MovePtr<Allocation>			inputImageAllocs[2]						{ (bindImage(vk, vkDevice, allocator, *inputImages[0], MemoryRequirement::Any))
258 																					, (bindImage(vk, vkDevice, allocator, *inputImages[1], MemoryRequirement::Any)) };
259 	Move<VkImageView>						inputImageViews[2]						{ (makeImageView(vk, vkDevice, *inputImages[0], VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange))
260 																					, (makeImageView(vk, vkDevice, *inputImages[1], VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange)) };
261 
262 	std::array<tcu::Vec4, 2>				testColors								{ tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f) };
263 
264 	const deUint32							descCount								= m_params.getDescCount();
265 
266 	for (int i = 0; i < 2; i++)
267 	{
268 		clearColorImage(vk, vkDevice, queue, queueFamilyIndex, inputImages[i].get(),
269 			testColors[i],
270 			VK_IMAGE_LAYOUT_UNDEFINED,
271 			finalImageLayout,
272 			pipelineStageFlags);
273 	}
274 
275 	std::vector<VkImage>					images;
276 	std::vector<VkImageView>				attachmentImages;
277 
278 	// Create Samplers
279 	const tcu::Sampler						sampler = tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, 0.0f, true, tcu::Sampler::COMPAREMODE_NONE, 0, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), true);
280 	const tcu::TextureFormat				texFormat								= mapVkFormat(colorFormat);
281 	const VkSamplerCreateInfo				samplerParams							= mapSampler(sampler, texFormat);
282 
283 	Move<VkSampler>							samplers[2]								= { createSampler(vk, vkDevice, &samplerParams)
284 																					, createSampler(vk, vkDevice, &samplerParams) };
285 
286 	// Create buffers
287 	const deUint32							bufferElementSize						= static_cast<deUint32>(sizeof(tcu::Vec4));
288 
289 	const Move<VkBuffer>					uboBuffers[2]							{ (makeBuffer(vk, vkDevice, bufferElementSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT))
290 																					, (makeBuffer(vk, vkDevice, bufferElementSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)) };
291 
292 	const Move<VkBuffer>					ssboBuffers[2]							{ (makeBuffer(vk, vkDevice, bufferElementSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT))
293 																					, (makeBuffer(vk, vkDevice, bufferElementSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)) };
294 
295 	const Move<VkBuffer>					compBufferResult						(makeBuffer(vk, vkDevice, bufferElementSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
296 
297 	const de::MovePtr<Allocation>			uboBufferAllocs[2]						{ (bindBuffer(vk, vkDevice, allocator, *uboBuffers[0], MemoryRequirement::HostVisible))
298 																					, (bindBuffer(vk, vkDevice, allocator, *uboBuffers[1], MemoryRequirement::HostVisible)) };
299 
300 	const de::MovePtr<Allocation>			ssboBufferAllocs[2]						{ (bindBuffer(vk, vkDevice, allocator, *ssboBuffers[0], MemoryRequirement::HostVisible))
301 																					, (bindBuffer(vk, vkDevice, allocator, *ssboBuffers[1], MemoryRequirement::HostVisible)) };
302 
303 	const de::MovePtr<Allocation>			ssboBufferAllocResult					(bindBuffer(vk, vkDevice, allocator, *compBufferResult, MemoryRequirement::HostVisible));
304 
305 	// Fill buffers
306 	{
307 		char*	pPosUbos[2]				= { static_cast<char*>(uboBufferAllocs[0]->getHostPtr())
308 										, static_cast<char*>(uboBufferAllocs[1]->getHostPtr()) };
309 
310 		char*	pPosSsbos[2]			= { static_cast<char*>(ssboBufferAllocs[0]->getHostPtr())
311 										, static_cast<char*>(ssboBufferAllocs[1]->getHostPtr()) };
312 
313 		char*	pPosSsboResult			= static_cast<char*>(ssboBufferAllocResult->getHostPtr());
314 
315 		*((tcu::Vec4*)pPosUbos[0])		= testColors[0];
316 		*((tcu::Vec4*)pPosUbos[1])		= testColors[1];
317 
318 		flushAlloc(vk, vkDevice, *uboBufferAllocs[0]);
319 		flushAlloc(vk, vkDevice, *uboBufferAllocs[1]);
320 
321 		*((tcu::Vec4*)pPosSsbos[0])		= testColors[0];
322 		*((tcu::Vec4*)pPosSsbos[1])		= testColors[1];
323 
324 		flushAlloc(vk, vkDevice, *ssboBufferAllocs[0]);
325 		flushAlloc(vk, vkDevice, *ssboBufferAllocs[1]);
326 
327 		*((tcu::Vec4*)pPosSsboResult)	= tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
328 
329 		flushAlloc(vk, vkDevice, *ssboBufferAllocResult);
330 	}
331 
332 	if (m_params.m_testType == TestType::InputAttachments)
333 	{
334 		for (deUint32 image = 0; image < 2; image++)
335 		{
336 			images.push_back(*inputImages[image]);
337 			attachmentImages.push_back(*inputImageViews[image]);
338 		}
339 	}
340 
341 	images.push_back(*colorImage);
342 	attachmentImages.push_back(*colorImageView);
343 
344 	// Result image buffer for fragment shader run
345 	const VkDeviceSize						resultImageBufferSizeBytes				= tcu::getPixelSize(mapVkFormat(colorFormat)) * m_params.m_framebufferSize.x() * m_params.m_framebufferSize.y();
346 	const Move<VkBuffer>					resultImageBuffer						(makeBuffer(vk, vkDevice, resultImageBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
347 	const de::MovePtr<Allocation>			resultImageBufferAlloc					(bindBuffer(vk, vkDevice, allocator, *resultImageBuffer, MemoryRequirement::HostVisible));
348 
349 	// Create vertex buffer
350 	const deUint32							numVertices								= 6;
351 	const VkDeviceSize						vertexBufferSizeBytes					= 256;
352 	Move<VkBuffer>							vertexBuffer							= (makeBuffer(vk, vkDevice, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
353 	de::MovePtr<Allocation>					vertexBufferAlloc						= (bindBuffer(vk, vkDevice, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
354 
355 	{
356 		tcu::Vec4* const	pVertices	= reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
357 
358 		pVertices[0]	= tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f);
359 		pVertices[1]	= tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f);
360 		pVertices[2]	= tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f);
361 		pVertices[3]	= tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f);
362 		pVertices[4]	= tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f);
363 		pVertices[5]	= tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f);
364 
365 		flushAlloc(vk, vkDevice, *vertexBufferAlloc);
366 	}
367 
368 	// Descriptor pool and descriptor set
369 	DescriptorPoolBuilder				poolBuilder;
370 
371 	// If compute pipeline is used for testing something else than SSBOs,
372 	// one SSBO descriptor is still needed for writing of the test result.
373 	if (m_params.m_testType != TestType::StorageBuffers && m_params.m_useCompShader)
374 	{
375 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u);
376 	}
377 
378 	if (m_params.m_testType == TestType::Samplers)
379 	{
380 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, descCount);
381 	}
382 
383 	if (m_params.m_testType == TestType::UniformBuffers)
384 	{
385 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descCount);
386 	}
387 
388 	if (m_params.m_testType == TestType::StorageBuffers)
389 	{
390 		// We must be an extra careful here.
391 		// Since the result buffer as well the input buffers are allocated from the same descriptor pool
392 		// full descriptor count should be used while allocating the pool when compute shader is used.
393 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_params.m_descCount);
394 	}
395 
396 	if (m_params.m_testType == TestType::SampledImages)
397 	{
398 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, descCount);
399 	}
400 
401 	if (m_params.m_testType == TestType::StorageImages)
402 	{
403 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descCount);
404 	}
405 
406 	if (m_params.m_testType == TestType::InputAttachments)
407 	{
408 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, descCount);
409 	}
410 
411 	const Move<VkDescriptorPool>			descriptorPool							= poolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u + (m_params.m_useCompShader ? 1u : 0u));
412 
413 	DescriptorSetLayoutBuilder				layoutBuilderAttachments;
414 
415 	if (m_params.m_testType == TestType::Samplers)
416 	{
417 		for (uint32_t i = 0; i < descCount; i++)
418 		{
419 			layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, shaderStageFlags);
420 		}
421 	}
422 
423 	if (m_params.m_testType == TestType::UniformBuffers)
424 	{
425 		for (uint32_t i = 0; i < descCount; i++)
426 		{
427 			layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, shaderStageFlags);
428 		}
429 	}
430 
431 	if (m_params.m_testType == TestType::StorageBuffers)
432 	{
433 		for (uint32_t i = 0; i < descCount; i++)
434 		{
435 			layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, shaderStageFlags);
436 		}
437 	}
438 
439 	if (m_params.m_testType == TestType::SampledImages)
440 	{
441 		for (uint32_t i = 0; i < descCount; i++)
442 		{
443 			layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, shaderStageFlags);
444 		}
445 	}
446 
447 	if (m_params.m_testType == TestType::StorageImages)
448 	{
449 		for (uint32_t i = 0; i < descCount; i++)
450 		{
451 			layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, shaderStageFlags);
452 		}
453 	}
454 
455 	if (m_params.m_testType == TestType::InputAttachments)
456 	{
457 		for (uint32_t i = 0; i < descCount; i++)
458 		{
459 			layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT);
460 		}
461 	}
462 
463 	const Move<VkDescriptorSetLayout>		descriptorSetLayout						= layoutBuilderAttachments.build(vk, vkDevice);
464 	const Move<VkDescriptorSet>				descriptorSet							= makeDescriptorSet(vk, vkDevice, descriptorPool.get(), descriptorSetLayout.get());
465 
466 
467 	DescriptorSetLayoutBuilder				layoutBuilderAttachmentsResult;
468 
469 	Move<VkDescriptorSetLayout>				descriptorSetLayoutResult;
470 	Move<VkDescriptorSet>					descriptorSetResult;
471 
472 	if (m_params.m_useCompShader)
473 	{
474 		layoutBuilderAttachmentsResult.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
475 
476 		descriptorSetLayoutResult	= layoutBuilderAttachmentsResult.build(vk, vkDevice);
477 		descriptorSetResult			= makeDescriptorSet(vk, vkDevice, descriptorPool.get(), descriptorSetLayoutResult.get());
478 	}
479 
480 	// Setup renderpass and framebuffer.
481 	RenderPassWrapper						renderPass;
482 	if (m_params.m_testType == TestType::InputAttachments)
483 		renderPass = (makeRenderPassInputAttachment(vk, vkDevice, m_params.m_pipelineConstructionType, colorFormat));
484 	else
485 		renderPass = (RenderPassWrapper(m_params.m_pipelineConstructionType, vk, vkDevice, colorFormat));
486 
487 	renderPass.createFramebuffer(vk, vkDevice, static_cast<deUint32>(attachmentImages.size()), images.data(), attachmentImages.data(), m_params.m_framebufferSize.x(), m_params.m_framebufferSize.y());
488 
489 	// Command buffer
490 	const Move<VkCommandPool>				cmdPool									(createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
491 	const Move<VkCommandBuffer>				cmdBuffer								(allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
492 
493 	std::vector<VkClearValue>				clearColorValues;
494 
495 	if (m_params.m_testType == TestType::InputAttachments)
496 	{
497 		clearColorValues.push_back(defaultClearValue(colorFormat));
498 		clearColorValues.push_back(defaultClearValue(colorFormat));
499 	}
500 
501 	clearColorValues.push_back(defaultClearValue(colorFormat));
502 
503 	const VkDeviceSize						vertexBufferOffset						= 0ull;
504 
505 	// Bind buffers
506 	const vk::VkDescriptorImageInfo			imageInfos[2]							= { makeDescriptorImageInfo(*samplers[0], *inputImageViews[0], m_params.m_testType == TestType::StorageImages
507 																					? VK_IMAGE_LAYOUT_GENERAL
508 																					: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
509 																					, makeDescriptorImageInfo(*samplers[1], *inputImageViews[1], m_params.m_testType == TestType::StorageImages
510 																					? VK_IMAGE_LAYOUT_GENERAL
511 																					: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) };
512 
513 	const vk::VkDescriptorBufferInfo		uboInfos[2]								= { makeDescriptorBufferInfo(*uboBuffers[0], 0u, bufferElementSize)
514 																					, makeDescriptorBufferInfo(*uboBuffers[1], 0u, bufferElementSize) };
515 
516 	const vk::VkDescriptorBufferInfo		ssboInfos[2]							= { makeDescriptorBufferInfo(*ssboBuffers[0], 0u, bufferElementSize)
517 																					, makeDescriptorBufferInfo(*ssboBuffers[1], 0u, bufferElementSize) };
518 
519 	const vk::VkDescriptorBufferInfo		ssboInfoResult							= makeDescriptorBufferInfo(*compBufferResult, 0u, bufferElementSize);
520 
521 	DescriptorSetUpdateBuilder				updateBuilder;
522 
523 	if (m_params.m_useCompShader)
524 	{
525 		updateBuilder.writeSingle(*descriptorSetResult, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &ssboInfoResult);
526 	}
527 
528 	if (m_params.m_testType == TestType::Samplers)
529 	{
530 		for (deUint32 bufferID = 0; bufferID < descCount - 1u; bufferID++)
531 		{
532 			updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bufferID), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageInfos[0]);
533 		}
534 
535 		updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descCount - 1u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageInfos[1]);
536 	}
537 
538 	if (m_params.m_testType == TestType::UniformBuffers)
539 	{
540 		for (deUint32 bufferID = 0; bufferID < descCount - 1u; bufferID++)
541 		{
542 			updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bufferID), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uboInfos[0]);
543 		}
544 
545 		updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descCount - 1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uboInfos[1]);
546 	}
547 
548 	if (m_params.m_testType == TestType::StorageBuffers)
549 	{
550 		for (deUint32 bufferID = 0; bufferID < (descCount - 1u); bufferID++)
551 		{
552 			updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bufferID), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &ssboInfos[0]);
553 		}
554 
555 		updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descCount - 1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &ssboInfos[1]);
556 	}
557 
558 	if (m_params.m_testType == TestType::SampledImages)
559 	{
560 		for (deUint32 bufferID = 0; bufferID < descCount - 1u; bufferID++)
561 		{
562 			updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bufferID), VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfos[0]);
563 		}
564 
565 		updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descCount - 1u), VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfos[1]);
566 	}
567 
568 	if (m_params.m_testType == TestType::StorageImages)
569 	{
570 		for (deUint32 bufferID = 0; bufferID < descCount - 1u; bufferID++)
571 		{
572 			updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bufferID), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageInfos[0]);
573 		}
574 
575 		updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descCount - 1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageInfos[1]);
576 	}
577 
578 	if (m_params.m_testType == TestType::InputAttachments)
579 	{
580 		for (deUint32 bufferID = 0; bufferID < descCount - 1u; bufferID++)
581 		{
582 			updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bufferID), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &imageInfos[0]);
583 		}
584 
585 		updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descCount - 1u), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &imageInfos[1]);
586 	}
587 
588 	updateBuilder.update(vk, vkDevice);
589 
590 	// Create pipeline layout
591 	std::vector<VkDescriptorSetLayout>		descSetLayouts							= { descriptorSetLayout.get() };
592 
593 	if (m_params.m_useCompShader)
594 	{
595 		descSetLayouts.push_back(descriptorSetLayoutResult.get());
596 	}
597 
598 	const VkPipelineLayoutCreateInfo		pipelineLayoutInfo						=
599 	{
600 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	// VkStructureType				sType;
601 		DE_NULL,										// const void*					pNext;
602 		0u,												// VkPipelineLayoutCreateFlags	flags;
603 		static_cast<deUint32>(descSetLayouts.size()),	// deUint32						descriptorSetCount;
604 		descSetLayouts.data(),							// const VkDescriptorSetLayout*	pSetLayouts;
605 		0u,												// deUint32						pushConstantRangeCount;
606 		DE_NULL											// const VkPushDescriptorRange*	pPushDescriptorRanges;
607 	};
608 
609 	const PipelineLayoutWrapper				pipelineLayout							(m_params.m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutInfo);
610 	Move<VkPipeline>						computePipeline							{};
611 	GraphicsPipelineWrapper					graphicsPipelineWrapper					{ vki, vk, physicalDevice, vkDevice, m_context.getDeviceExtensions(), m_params.m_pipelineConstructionType };
612 
613 	if (m_params.m_useCompShader)
614 	{
615 		computePipeline = (makeComputePipeline(vk, vkDevice, pipelineLayout.get(), testedShaderModule.getModule()));
616 	}
617 	else
618 	{
619 		const std::vector<VkViewport>	viewports	{ makeViewport(m_params.m_framebufferSize) };
620 		const std::vector<VkRect2D>		scissors	{ makeRect2D(m_params.m_framebufferSize) };
621 		VkSampleMask					sampleMask	= 0x1;
622 
623 		const VkPipelineMultisampleStateCreateInfo	multisampleStateCreateInfo
624 		{
625 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType
626 			DE_NULL,													// const void*								pNext
627 			0u,															// VkPipelineMultisampleStateCreateFlags	flags
628 			VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples
629 			DE_FALSE,													// VkBool32									sampleShadingEnable
630 			0.0f,														// float									minSampleShading
631 			&sampleMask,												// const VkSampleMask*						pSampleMask
632 			DE_FALSE,													// VkBool32									alphaToCoverageEnable
633 			DE_FALSE,													// VkBool32									alphaToOneEnable
634 		};
635 
636 		graphicsPipelineWrapper.setDefaultDepthStencilState()
637 			.setDefaultColorBlendState()
638 			.setDefaultRasterizationState()
639 			.setupVertexInputState()
640 			.setupPreRasterizationShaderState(viewports,
641 				scissors,
642 				pipelineLayout,
643 				renderPass.get(),
644 				0u,
645 				vertexShaderModule)
646 			.setupFragmentShaderState(pipelineLayout,
647 				renderPass.get(),
648 				0u,
649 				testedShaderModule,
650 				DE_NULL,
651 				&multisampleStateCreateInfo)
652 			.setupFragmentOutputState(renderPass.get(), 0u, DE_NULL, &multisampleStateCreateInfo)
653 			.setMonolithicPipelineLayout(pipelineLayout)
654 			.buildPipeline();
655 	}
656 
657 	beginCommandBuffer(vk, *cmdBuffer);
658 
659 	if (m_params.m_useCompShader)
660 	{
661 		const std::vector<VkDescriptorSet> descSets = { descriptorSet.get(), descriptorSetResult.get() };
662 
663 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline.get());
664 		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, static_cast<deUint32>(descSets.size()), descSets.data(), 0u, DE_NULL);
665 		vk.cmdDispatch(*cmdBuffer, 1u, 1u, 1u);
666 	}
667 	else
668 	{
669 		renderPass.begin(vk, *cmdBuffer, makeRect2D(0, 0, m_params.m_framebufferSize.x(), m_params.m_framebufferSize.y()), static_cast<deUint32>(clearColorValues.size()), clearColorValues.data());
670 		graphicsPipelineWrapper.bind(*cmdBuffer);
671 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
672 		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
673 		vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
674 		renderPass.end(vk, *cmdBuffer);
675 		copyImageToBuffer(vk, *cmdBuffer, *colorImage, *resultImageBuffer, m_params.m_framebufferSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
676 	}
677 
678 	endCommandBuffer(vk, *cmdBuffer);
679 
680 	submitCommandsAndWait(vk, vkDevice, queue, *cmdBuffer);
681 
682 	// Check results
683 	if (!m_params.m_useCompShader)
684 	{
685 		invalidateAlloc(vk, vkDevice, *resultImageBufferAlloc);
686 
687 		const tcu::ConstPixelBufferAccess	imagePixelAccess	(mapVkFormat(colorFormat), m_params.m_framebufferSize.x(), m_params.m_framebufferSize.y(), 1, resultImageBufferAlloc->getHostPtr());
688 		const tcu::TextureLevel				referenceTexture	= generateColorImage(colorFormat, m_params.m_framebufferSize, testColors[1]);
689 
690 		if (!tcu::floatThresholdCompare(log, "Compare color output", "Image result comparison", referenceTexture.getAccess(), imagePixelAccess, tcu::Vec4(0.0f), tcu::COMPARE_LOG_RESULT))
691 			return tcu::TestStatus::fail("Rendered color image is not correct");
692 	}
693 	else
694 	{
695 		invalidateAlloc(vk, vkDevice, *ssboBufferAllocResult);
696 		const tcu::Vec4	resultValue	= *static_cast<tcu::Vec4*>(ssboBufferAllocResult->getHostPtr());
697 
698 		if (!(resultValue == tcu::Vec4(0.0, 1.0, 0.0, 1.0)))
699 			return tcu::TestStatus::fail("Result buffer value is not correct");
700 	}
701 
702 	return tcu::TestStatus::pass("Success");
703 }
704 
705 class DescriptorLimitTest : public vkt::TestCase
706 {
707 public:
DescriptorLimitTest(tcu::TestContext& testContext, const std::string& name, const TestParams& params)708 							DescriptorLimitTest		(tcu::TestContext&				testContext,
709 													 const std::string&				name,
710 													 const TestParams&				params)
711 							: TestCase(testContext, name)
712 							, m_params						(params)
713 							{}
714 
~DescriptorLimitTest(void)715 	virtual					~DescriptorLimitTest	(void)
716 							{}
717 
718 	virtual void			initPrograms			(SourceCollections& programCollection) const;
719 	virtual void			checkSupport			(Context& context) const;
720 	virtual TestInstance*	createInstance			(Context& context) const;
721 
722 private:
723 	TestParams	m_params;
724 };
725 
initPrograms(SourceCollections& sourceCollections) const726 void DescriptorLimitTest::initPrograms (SourceCollections& sourceCollections) const
727 {
728 	std::ostringstream	testTypeStr;
729 	std::ostringstream	fragResultStr;
730 	std::ostringstream	compResultStr;
731 	const deUint32		descCount		= m_params.getDescCount();
732 
733 	if (m_params.m_testType == TestType::Samplers)
734 	{
735 		testTypeStr		<< "layout(set = 0, binding = " << descCount - 1u << ") uniform sampler2D texSamplerInput;\n";
736 
737 		fragResultStr	<<	"    const vec2 coords = vec2(0, 0);\n"
738 						<<	"    fragColor = texture(texSamplerInput, coords);\n";
739 
740 		compResultStr	<<	"    const vec2 coords = vec2(0, 0);\n"
741 						<<	"    outputData.color = texture(texSamplerInput, coords);\n";
742 	}
743 
744 	if (m_params.m_testType == TestType::UniformBuffers)
745 	{
746 		testTypeStr		<< "layout(set = 0, binding = " << descCount - 1u << ") uniform uboInput\n"
747 						<< "{\n"
748 						<< "    vec4 color;\n"
749 						<< "} inputData;\n"
750 						<< "\n";
751 
752 		fragResultStr	<< "    fragColor = inputData.color;\n";
753 		compResultStr	<< "    outputData.color = inputData.color;\n";
754 	}
755 
756 	if (m_params.m_testType == TestType::StorageBuffers)
757 	{
758 		testTypeStr		<< "layout(set = 0, binding = " << (descCount - 1u) << ") readonly buffer ssboInput\n"
759 						<< "{\n"
760 						<< "    vec4 color;\n"
761 						<< "} inputData;\n"
762 						<< "\n";
763 
764 		fragResultStr	<< "    fragColor = inputData.color;\n";
765 		compResultStr	<< "    outputData.color = inputData.color;\n";
766 	}
767 
768 	if (m_params.m_testType == TestType::SampledImages)
769 	{
770 		testTypeStr		<< "#extension GL_EXT_samplerless_texture_functions : enable\n"
771 						<< "layout(set = 0, binding = " << descCount - 1u << ") uniform texture2D imageInput;\n";
772 
773 		fragResultStr	<< "    fragColor = texelFetch(imageInput, ivec2(gl_FragCoord.xy), 0);\n";
774 		compResultStr	<< "    const ivec2 coords = ivec2(0, 0);\n"
775 						<< "    outputData.color = texelFetch(imageInput, coords, 0);\n";
776 	}
777 
778 	if (m_params.m_testType == TestType::StorageImages)
779 	{
780 		testTypeStr		<< "#extension GL_EXT_samplerless_texture_functions : enable\n"
781 						<< "layout(set = 0, binding = " << descCount - 1u << ", rgba8) uniform image2D imageInput;\n";
782 
783 		fragResultStr	<< "    fragColor = imageLoad(imageInput, ivec2(gl_FragCoord.xy));\n";
784 		compResultStr	<< "    const ivec2 coords = ivec2(0, 0);\n"
785 						<< "    outputData.color = imageLoad(imageInput, coords);\n";
786 	}
787 
788 	if (m_params.m_testType == TestType::InputAttachments)
789 	{
790 		testTypeStr << "layout (input_attachment_index = 1, set = 0, binding = " << descCount - 1u << ") uniform subpassInput imageInput;\n";
791 
792 		fragResultStr	<< "    fragColor = subpassLoad(imageInput);\n";
793 		compResultStr	<< "    outputData.color = vec4(0.0, 0.0, 0.0, 1.0);\n";
794 	}
795 
796 	std::ostringstream vertexSrc;
797 	vertexSrc	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
798 				<< "\n"
799 				<< "layout(location = 0) in vec4 position;\n"
800 				<< "\n"
801 				<< "void main (void)\n"
802 				<< "{\n"
803 				<< "    gl_Position = position;\n"
804 				<< "}\n";
805 
806 	sourceCollections.glslSources.add("vert") << glu::VertexSource(vertexSrc.str());
807 
808 	std::ostringstream testSrc;
809 
810 	if (!m_params.m_useCompShader)
811 	{
812 		testSrc << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
813 			<< "\n"
814 			<< "layout(location = 0) out vec4 fragColor;\n"
815 			<< "\n"
816 			<< testTypeStr.str()
817 			<< "void main (void)\n"
818 			<< "{\n"
819 			<< fragResultStr.str()
820 			<< "}\n";
821 
822 		sourceCollections.glslSources.add("test") << glu::FragmentSource(testSrc.str());
823 	}
824 	else
825 	{
826 		testSrc	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
827 				<< "\n"
828 				// Input attachments are not supported by compute shaders.
829 				<< (m_params.m_testType != TestType::InputAttachments ? testTypeStr.str() : "")
830 				<< "layout(set = 1, binding = 0) buffer ssboOutput\n"
831 				<< "{\n"
832 				<< "    vec4 color;\n"
833 				<< "} outputData;\n"
834 				<< "\n"
835 				<< "void main (void)\n"
836 				<< "{\n"
837 				<< compResultStr.str()
838 				<< "}\n";
839 
840 		sourceCollections.glslSources.add("test") << glu::ComputeSource(testSrc.str());
841 	}
842 }
843 
checkSupport(Context& context) const844 void DescriptorLimitTest::checkSupport (Context& context) const
845 {
846 	const InstanceInterface&		vki				= context.getInstanceInterface();
847 	const VkPhysicalDevice			physDevice		= context.getPhysicalDevice();
848 	const VkPhysicalDeviceLimits	limits			= getPhysicalDeviceProperties(vki, physDevice).limits;
849 
850 	// We have to make sure, that we don't bind anything outside of valid descriptor binding locations determined by maxPerStageResources.
851 	if (m_params.m_descCount > limits.maxPerStageResources - 1u)
852 		TCU_THROW(NotSupportedError, "maxPerStageResources (" + std::to_string(limits.maxPerStageResources) + ")");
853 
854 	if (m_params.m_testType == TestType::Samplers)
855 	{
856 		if(m_params.m_descCount > limits.maxPerStageDescriptorSamplers)
857 			TCU_THROW(NotSupportedError, "maxPerStageDescriptorSamplers (" + std::to_string(limits.maxPerStageDescriptorSamplers) + ")");
858 	}
859 
860 	if (m_params.m_testType == TestType::UniformBuffers)
861 	{
862 		if (m_params.m_descCount > limits.maxPerStageDescriptorUniformBuffers)
863 			TCU_THROW(NotSupportedError, "maxPerStageDescriptorUniformBuffers (" + std::to_string(limits.maxPerStageDescriptorUniformBuffers) + ")");
864 	}
865 
866 	if (m_params.m_testType == TestType::StorageBuffers)
867 	{
868 		if (m_params.m_descCount > limits.maxPerStageDescriptorStorageBuffers)
869 			TCU_THROW(NotSupportedError, "maxPerStageDescriptorStorageBuffers (" + std::to_string(limits.maxPerStageDescriptorStorageBuffers) + ")");
870 	}
871 
872 	if (m_params.m_testType == TestType::SampledImages)
873 	{
874 		if (m_params.m_descCount > limits.maxPerStageDescriptorSampledImages)
875 			TCU_THROW(NotSupportedError, "maxPerStageDescriptorSampledImages (" + std::to_string(limits.maxPerStageDescriptorSampledImages) + ")");
876 	}
877 
878 	if (m_params.m_testType == TestType::StorageImages)
879 	{
880 		if (m_params.m_descCount > limits.maxPerStageDescriptorStorageImages)
881 			TCU_THROW(NotSupportedError, "maxPerStageDescriptorStorageImages (" + std::to_string(limits.maxPerStageDescriptorStorageImages) + ")");
882 	}
883 
884 	if (m_params.m_testType == TestType::InputAttachments)
885 	{
886 		if (m_params.m_descCount > limits.maxPerStageDescriptorInputAttachments)
887 			TCU_THROW(NotSupportedError, "maxPerStageDescriptorInputAttachments (" + std::to_string(limits.maxPerStageDescriptorInputAttachments) + ")");
888 	}
889 
890 	checkPipelineConstructionRequirements(vki, physDevice, m_params.m_pipelineConstructionType);
891 }
892 
createInstance(Context& context) const893 TestInstance* DescriptorLimitTest::createInstance (Context& context) const
894 {
895 	return new DescriptorLimitTestInstance(context, m_params);
896 }
897 
898 }
899 
createDescriptorLimitsTests(tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)900 tcu::TestCaseGroup* createDescriptorLimitsTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
901 {
902 	de::MovePtr<tcu::TestCaseGroup>	descriptorLimitTestGroup	(new tcu::TestCaseGroup(testCtx, "descriptor_limits"));
903 	const tcu::IVec2				frameBufferSize				= tcu::IVec2(32, 32);
904 
905 	const std::vector<deUint32>		numDescriptors				=
906 	{
907 		3u,		4u,		5u,		6u,		7u,		8u,		9u,		10u,	11u,
908 		12u,	13u,	14u,	15u,	16u,	17u,	18u,	19u,	20u,
909 		31u,	32u,	63u,	64u,	100u,	127u,	128u,	199u,	200u,
910 		256u,	512u,	1024u,	2048u,	4096u,	8192u,	16384u,	32768u,	65535u
911 	};
912 
913 	if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
914 	{
915 		de::MovePtr<tcu::TestCaseGroup>	computeShaderGroup(new tcu::TestCaseGroup(testCtx, "compute_shader"));
916 
917 		for (const auto& descId : numDescriptors)
918 		{
919 			const deUint32	testValue		= descId;
920 
921 			{
922 				TestParams params(pipelineConstructionType, TestType::Samplers, true, frameBufferSize, testValue);
923 				computeShaderGroup->addChild(new DescriptorLimitTest(testCtx, "samplers_" + std::to_string(testValue), params));
924 			}
925 
926 			{
927 				TestParams params(pipelineConstructionType, TestType::UniformBuffers, true, frameBufferSize, testValue);
928 				computeShaderGroup->addChild(new DescriptorLimitTest(testCtx, "uniform_buffers_" + std::to_string(testValue), params));
929 			}
930 
931 			{
932 				TestParams params(pipelineConstructionType, TestType::StorageBuffers, true, frameBufferSize, testValue);
933 				computeShaderGroup->addChild(new DescriptorLimitTest(testCtx, "storage_buffers_" + std::to_string(testValue), params));
934 			}
935 
936 			{
937 				TestParams params(pipelineConstructionType, TestType::SampledImages, true, frameBufferSize, testValue);
938 				computeShaderGroup->addChild(new DescriptorLimitTest(testCtx, "sampled_images_" + std::to_string(testValue), params));
939 			}
940 
941 			{
942 				TestParams params(pipelineConstructionType, TestType::StorageImages, true, frameBufferSize, testValue);
943 				computeShaderGroup->addChild(new DescriptorLimitTest(testCtx, "storage_images_" + std::to_string(testValue), params));
944 			}
945 		}
946 
947 		descriptorLimitTestGroup->addChild(computeShaderGroup.release());
948 	}
949 
950 	de::MovePtr<tcu::TestCaseGroup>	fragmentShaderGroup(new tcu::TestCaseGroup(testCtx, "fragment_shader"));
951 
952 	for (const auto& descId : numDescriptors)
953 	{
954 		const deUint32	testValue	= descId;
955 
956 		{
957 			TestParams params(pipelineConstructionType, TestType::Samplers, false, frameBufferSize, testValue);
958 			fragmentShaderGroup->addChild(new DescriptorLimitTest(testCtx, "samplers_" + std::to_string(testValue), params));
959 		}
960 
961 		{
962 			TestParams params(pipelineConstructionType, TestType::UniformBuffers, false, frameBufferSize, testValue);
963 			fragmentShaderGroup->addChild(new DescriptorLimitTest(testCtx, "uniform_buffers_" + std::to_string(testValue), params));
964 		}
965 
966 		{
967 			TestParams params(pipelineConstructionType, TestType::StorageBuffers, false, frameBufferSize, testValue);
968 			fragmentShaderGroup->addChild(new DescriptorLimitTest(testCtx, "storage_buffers_" + std::to_string(testValue), params));
969 		}
970 
971 		{
972 			TestParams params(pipelineConstructionType, TestType::SampledImages, false, frameBufferSize, testValue);
973 			fragmentShaderGroup->addChild(new DescriptorLimitTest(testCtx, "sampled_images_" + std::to_string(testValue), params));
974 		}
975 
976 		{
977 			TestParams params(pipelineConstructionType, TestType::StorageImages, false, frameBufferSize, testValue);
978 			fragmentShaderGroup->addChild(new DescriptorLimitTest(testCtx, "storage_images_" + std::to_string(testValue), params));
979 		}
980 
981 		if (!vk::isConstructionTypeShaderObject(pipelineConstructionType))
982 		{
983 			TestParams params(pipelineConstructionType, TestType::InputAttachments, false, frameBufferSize, testValue);
984 			fragmentShaderGroup->addChild(new DescriptorLimitTest(testCtx, "input_attachments_" + std::to_string(testValue), params));
985 		}
986 	}
987 
988 	descriptorLimitTestGroup->addChild(fragmentShaderGroup.release());
989 
990 	return descriptorLimitTestGroup.release();
991 }
992 
993 } // pipeline
994 } // vkt
995