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