• 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 struct TestParams
162 {
TestParamsvkt::pipeline::__anon779459d80111::TestParams163 	TestParams	(const PipelineConstructionType	pipelineConstructionType,
164 				const TestType					testType,
165 				const bool						useCompShader,
166 				const tcu::IVec2				framebufferSize,
167 				const deUint32					descCount)
168 				: m_pipelineConstructionType	(pipelineConstructionType)
169 				, m_testType					(testType)
170 				, m_useCompShader				(useCompShader)
171 				, m_framebufferSize				(framebufferSize)
172 				, m_descCount					(descCount)
173 	{}
174 
175 	const PipelineConstructionType	m_pipelineConstructionType;
176 	const TestType					m_testType;
177 	const bool						m_useCompShader;
178 	const tcu::IVec2				m_framebufferSize;
179 	const deUint32					m_descCount;
180 
getDescCountvkt::pipeline::__anon779459d80111::TestParams181 	deUint32 getDescCount() const
182 	{
183 		deUint32 descCnt = m_descCount;
184 
185 		if (m_testType == TestType::StorageBuffers && m_useCompShader)
186 			descCnt = m_descCount - 1u;
187 
188 		return descCnt;
189 	}
190 };
191 
192 class DescriptorLimitTestInstance : public vkt::TestInstance
193 {
194 public:
DescriptorLimitTestInstance(Context & context,const TestParams & params)195 							DescriptorLimitTestInstance		(Context&						context,
196 															const TestParams&				params)
197 															: vkt::TestInstance				(context)
198 															, m_params						(params)
199 							{}
200 
~DescriptorLimitTestInstance()201 							~DescriptorLimitTestInstance	()
202 							{}
203 
204 	virtual tcu::TestStatus	iterate							(void);
205 
206 private:
207 	struct BufferInfo
208 	{
209 		tcu::Vec4	color;
210 	};
211 	TestParams	m_params;
212 };
213 
iterate(void)214 tcu::TestStatus DescriptorLimitTestInstance::iterate (void)
215 {
216 	tcu::TestLog&							log										= m_context.getTestContext().getLog();
217 	const DeviceInterface&					vk										= m_context.getDeviceInterface();
218 	const VkDevice							vkDevice								= m_context.getDevice();
219 	Allocator&								allocator								= m_context.getDefaultAllocator();
220 	const VkQueue							queue									= m_context.getUniversalQueue();
221 	const deUint32							queueFamilyIndex						= m_context.getUniversalQueueFamilyIndex();
222 	VkFormat								colorFormat								= VK_FORMAT_R8G8B8A8_UNORM;
223 
224 	// Pick correct test parameters based on test type
225 	const VkShaderStageFlags				shaderStageFlags						= m_params.m_useCompShader ? VkShaderStageFlags(VK_SHADER_STAGE_COMPUTE_BIT) : VkShaderStageFlags(VK_SHADER_STAGE_FRAGMENT_BIT);
226 	const VkPipelineStageFlags				pipelineStageFlags						= m_params.m_useCompShader ? VkPipelineStageFlags(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT) : VkPipelineStageFlags(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
227 
228 	const VkImageUsageFlags					imageFlags								= m_params.m_testType == TestType::InputAttachments
229 																					? VkImageUsageFlags(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)
230 																					: m_params.m_testType == TestType::StorageImages
231 																					? VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT
232 																					: VkImageUsageFlags(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
233 
234 	const VkImageLayout						finalImageLayout						= m_params.m_testType == TestType::InputAttachments
235 																					? VkImageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
236 																					: m_params.m_testType == TestType::StorageImages
237 																					? VkImageLayout(VK_IMAGE_LAYOUT_GENERAL)
238 																					: VkImageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
239 
240 	// Create shaders
241 	Move<VkShaderModule>					vertexShaderModule						= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vert"), 0u);
242 	Move<VkShaderModule>					testedShaderModule						= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("test"), 0u);
243 
244 	// Create images
245 	const VkImageSubresourceRange			colorSubresourceRange					= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
246 	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)));
247 	const de::MovePtr<Allocation>			colorImageAlloc							(bindImage(vk, vkDevice, allocator, *colorImage, MemoryRequirement::Any));
248 	const Move<VkImageView>					colorImageView							(makeImageView(vk, vkDevice, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
249 
250 	const Move<VkImage>						inputImages[2]							{ (makeImage(vk, vkDevice, makeImageCreateInfo(m_params.m_framebufferSize, colorFormat, imageFlags)))
251 																					, (makeImage(vk, vkDevice, makeImageCreateInfo(m_params.m_framebufferSize, colorFormat, imageFlags))) };
252 	const de::MovePtr<Allocation>			inputImageAllocs[2]						{ (bindImage(vk, vkDevice, allocator, *inputImages[0], MemoryRequirement::Any))
253 																					, (bindImage(vk, vkDevice, allocator, *inputImages[1], MemoryRequirement::Any)) };
254 	Move<VkImageView>						inputImageViews[2]						{ (makeImageView(vk, vkDevice, *inputImages[0], VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange))
255 																					, (makeImageView(vk, vkDevice, *inputImages[1], VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange)) };
256 
257 	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) };
258 
259 	const deUint32							descCount								= m_params.getDescCount();
260 
261 	for (int i = 0; i < 2; i++)
262 	{
263 		clearColorImage(vk, vkDevice, queue, queueFamilyIndex, inputImages[i].get(),
264 			testColors[i],
265 			VK_IMAGE_LAYOUT_UNDEFINED,
266 			finalImageLayout,
267 			pipelineStageFlags);
268 	}
269 
270 	std::vector<VkImageView>				attachmentImages;
271 
272 	// Create Samplers
273 	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);
274 	const tcu::TextureFormat				texFormat								= mapVkFormat(colorFormat);
275 	const VkSamplerCreateInfo				samplerParams							= mapSampler(sampler, texFormat);
276 
277 	Move<VkSampler>							samplers[2]								= { createSampler(vk, vkDevice, &samplerParams)
278 																					, createSampler(vk, vkDevice, &samplerParams) };
279 
280 	// Create buffers
281 	const deUint32							bufferElementSize						= static_cast<deUint32>(sizeof(tcu::Vec4));
282 
283 	const Move<VkBuffer>					uboBuffers[2]							{ (makeBuffer(vk, vkDevice, bufferElementSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT))
284 																					, (makeBuffer(vk, vkDevice, bufferElementSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)) };
285 
286 	const Move<VkBuffer>					ssboBuffers[2]							{ (makeBuffer(vk, vkDevice, bufferElementSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT))
287 																					, (makeBuffer(vk, vkDevice, bufferElementSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)) };
288 
289 	const Move<VkBuffer>					compBufferResult						(makeBuffer(vk, vkDevice, bufferElementSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
290 
291 	const de::MovePtr<Allocation>			uboBufferAllocs[2]						{ (bindBuffer(vk, vkDevice, allocator, *uboBuffers[0], MemoryRequirement::HostVisible))
292 																					, (bindBuffer(vk, vkDevice, allocator, *uboBuffers[1], MemoryRequirement::HostVisible)) };
293 
294 	const de::MovePtr<Allocation>			ssboBufferAllocs[2]						{ (bindBuffer(vk, vkDevice, allocator, *ssboBuffers[0], MemoryRequirement::HostVisible))
295 																					, (bindBuffer(vk, vkDevice, allocator, *ssboBuffers[1], MemoryRequirement::HostVisible)) };
296 
297 	const de::MovePtr<Allocation>			ssboBufferAllocResult					(bindBuffer(vk, vkDevice, allocator, *compBufferResult, MemoryRequirement::HostVisible));
298 
299 	// Fill buffers
300 	{
301 		char*	pPosUbos[2]				= { static_cast<char*>(uboBufferAllocs[0]->getHostPtr())
302 										, static_cast<char*>(uboBufferAllocs[1]->getHostPtr()) };
303 
304 		char*	pPosSsbos[2]			= { static_cast<char*>(ssboBufferAllocs[0]->getHostPtr())
305 										, static_cast<char*>(ssboBufferAllocs[1]->getHostPtr()) };
306 
307 		char*	pPosSsboResult			= static_cast<char*>(ssboBufferAllocResult->getHostPtr());
308 
309 		*((tcu::Vec4*)pPosUbos[0])		= testColors[0];
310 		*((tcu::Vec4*)pPosUbos[1])		= testColors[1];
311 
312 		flushAlloc(vk, vkDevice, *uboBufferAllocs[0]);
313 		flushAlloc(vk, vkDevice, *uboBufferAllocs[1]);
314 
315 		*((tcu::Vec4*)pPosSsbos[0])		= testColors[0];
316 		*((tcu::Vec4*)pPosSsbos[1])		= testColors[1];
317 
318 		flushAlloc(vk, vkDevice, *ssboBufferAllocs[0]);
319 		flushAlloc(vk, vkDevice, *ssboBufferAllocs[1]);
320 
321 		*((tcu::Vec4*)pPosSsboResult)	= tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
322 
323 		flushAlloc(vk, vkDevice, *ssboBufferAllocResult);
324 	}
325 
326 	if (m_params.m_testType == TestType::InputAttachments)
327 	{
328 		for (deUint32 image = 0; image < 2; image++)
329 		{
330 			attachmentImages.push_back(*inputImageViews[image]);
331 		}
332 	}
333 
334 	attachmentImages.push_back(*colorImageView);
335 
336 	// Result image buffer for fragment shader run
337 	const VkDeviceSize						resultImageBufferSizeBytes				= tcu::getPixelSize(mapVkFormat(colorFormat)) * m_params.m_framebufferSize.x() * m_params.m_framebufferSize.y();
338 	const Move<VkBuffer>					resultImageBuffer						(makeBuffer(vk, vkDevice, resultImageBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
339 	const de::MovePtr<Allocation>			resultImageBufferAlloc					(bindBuffer(vk, vkDevice, allocator, *resultImageBuffer, MemoryRequirement::HostVisible));
340 
341 	// Create vertex buffer
342 	const deUint32							numVertices								= 6;
343 	const VkDeviceSize						vertexBufferSizeBytes					= 256;
344 	Move<VkBuffer>							vertexBuffer							= (makeBuffer(vk, vkDevice, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
345 	de::MovePtr<Allocation>					vertexBufferAlloc						= (bindBuffer(vk, vkDevice, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
346 
347 	{
348 		tcu::Vec4* const	pVertices	= reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
349 
350 		pVertices[0]	= tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f);
351 		pVertices[1]	= tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f);
352 		pVertices[2]	= tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f);
353 		pVertices[3]	= tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f);
354 		pVertices[4]	= tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f);
355 		pVertices[5]	= tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f);
356 
357 		flushAlloc(vk, vkDevice, *vertexBufferAlloc);
358 	}
359 
360 	// Descriptor pool and descriptor set
361 	DescriptorPoolBuilder				poolBuilder;
362 
363 	// If compute pipeline is used for testing something else than SSBOs,
364 	// one SSBO descriptor is still needed for writing of the test result.
365 	if (m_params.m_testType != TestType::StorageBuffers && m_params.m_useCompShader)
366 	{
367 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u);
368 	}
369 
370 	if (m_params.m_testType == TestType::Samplers)
371 	{
372 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, descCount);
373 	}
374 
375 	if (m_params.m_testType == TestType::UniformBuffers)
376 	{
377 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descCount);
378 	}
379 
380 	if (m_params.m_testType == TestType::StorageBuffers)
381 	{
382 		// We must be an extra careful here.
383 		// Since the result buffer as well the input buffers are allocated from the same descriptor pool
384 		// full descriptor count should be used while allocating the pool when compute shader is used.
385 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_params.m_descCount);
386 	}
387 
388 	if (m_params.m_testType == TestType::SampledImages)
389 	{
390 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, descCount);
391 	}
392 
393 	if (m_params.m_testType == TestType::StorageImages)
394 	{
395 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descCount);
396 	}
397 
398 	if (m_params.m_testType == TestType::InputAttachments)
399 	{
400 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, descCount);
401 	}
402 
403 	const Move<VkDescriptorPool>			descriptorPool							= poolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u + (m_params.m_useCompShader ? 1u : 0u));
404 
405 	DescriptorSetLayoutBuilder				layoutBuilderAttachments;
406 
407 	if (m_params.m_testType == TestType::Samplers)
408 	{
409 		for (uint32_t i = 0; i < descCount; i++)
410 		{
411 			layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, shaderStageFlags);
412 		}
413 	}
414 
415 	if (m_params.m_testType == TestType::UniformBuffers)
416 	{
417 		for (uint32_t i = 0; i < descCount; i++)
418 		{
419 			layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, shaderStageFlags);
420 		}
421 	}
422 
423 	if (m_params.m_testType == TestType::StorageBuffers)
424 	{
425 		for (uint32_t i = 0; i < descCount; i++)
426 		{
427 			layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, shaderStageFlags);
428 		}
429 	}
430 
431 	if (m_params.m_testType == TestType::SampledImages)
432 	{
433 		for (uint32_t i = 0; i < descCount; i++)
434 		{
435 			layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, shaderStageFlags);
436 		}
437 	}
438 
439 	if (m_params.m_testType == TestType::StorageImages)
440 	{
441 		for (uint32_t i = 0; i < descCount; i++)
442 		{
443 			layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, shaderStageFlags);
444 		}
445 	}
446 
447 	if (m_params.m_testType == TestType::InputAttachments)
448 	{
449 		for (uint32_t i = 0; i < descCount; i++)
450 		{
451 			layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT);
452 		}
453 	}
454 
455 	const Move<VkDescriptorSetLayout>		descriptorSetLayout						= layoutBuilderAttachments.build(vk, vkDevice);
456 	const Move<VkDescriptorSet>				descriptorSet							= makeDescriptorSet(vk, vkDevice, descriptorPool.get(), descriptorSetLayout.get());
457 
458 
459 	DescriptorSetLayoutBuilder				layoutBuilderAttachmentsResult;
460 
461 	Move<VkDescriptorSetLayout>				descriptorSetLayoutResult;
462 	Move<VkDescriptorSet>					descriptorSetResult;
463 
464 	if (m_params.m_useCompShader)
465 	{
466 		layoutBuilderAttachmentsResult.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
467 
468 		descriptorSetLayoutResult	= layoutBuilderAttachmentsResult.build(vk, vkDevice);
469 		descriptorSetResult			= makeDescriptorSet(vk, vkDevice, descriptorPool.get(), descriptorSetLayoutResult.get());
470 	}
471 
472 	// Setup renderpass and framebuffer.
473 	const Move<VkRenderPass>				renderPass								(m_params.m_testType == TestType::InputAttachments
474 																					? (makeRenderPassInputAttachment(vk, vkDevice, colorFormat))
475 																					: (makeRenderPass(vk, vkDevice, colorFormat)));
476 
477 	const Move<VkFramebuffer>				framebuffer								(makeFramebuffer(vk, vkDevice, *renderPass, static_cast<deUint32>(attachmentImages.size()), attachmentImages.data(), m_params.m_framebufferSize.x(), m_params.m_framebufferSize.y()));
478 
479 	// Command buffer
480 	const Move<VkCommandPool>				cmdPool									(createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
481 	const Move<VkCommandBuffer>				cmdBuffer								(allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
482 
483 	std::vector<VkClearValue>				clearColorValues;
484 
485 	if (m_params.m_testType == TestType::InputAttachments)
486 	{
487 		clearColorValues.push_back(defaultClearValue(colorFormat));
488 		clearColorValues.push_back(defaultClearValue(colorFormat));
489 	}
490 
491 	clearColorValues.push_back(defaultClearValue(colorFormat));
492 
493 	const VkDeviceSize						vertexBufferOffset						= 0ull;
494 
495 	// Bind buffers
496 	const vk::VkDescriptorImageInfo			imageInfos[2]							= { makeDescriptorImageInfo(*samplers[0], *inputImageViews[0], m_params.m_testType == TestType::StorageImages
497 																					? VK_IMAGE_LAYOUT_GENERAL
498 																					: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
499 																					, makeDescriptorImageInfo(*samplers[1], *inputImageViews[1], m_params.m_testType == TestType::StorageImages
500 																					? VK_IMAGE_LAYOUT_GENERAL
501 																					: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) };
502 
503 	const vk::VkDescriptorBufferInfo		uboInfos[2]								= { makeDescriptorBufferInfo(*uboBuffers[0], 0u, bufferElementSize)
504 																					, makeDescriptorBufferInfo(*uboBuffers[1], 0u, bufferElementSize) };
505 
506 	const vk::VkDescriptorBufferInfo		ssboInfos[2]							= { makeDescriptorBufferInfo(*ssboBuffers[0], 0u, bufferElementSize)
507 																					, makeDescriptorBufferInfo(*ssboBuffers[1], 0u, bufferElementSize) };
508 
509 	const vk::VkDescriptorBufferInfo		ssboInfoResult							= makeDescriptorBufferInfo(*compBufferResult, 0u, bufferElementSize);
510 
511 	DescriptorSetUpdateBuilder				updateBuilder;
512 
513 	if (m_params.m_useCompShader)
514 	{
515 		updateBuilder.writeSingle(*descriptorSetResult, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &ssboInfoResult);
516 	}
517 
518 	if (m_params.m_testType == TestType::Samplers)
519 	{
520 		for (deUint32 bufferID = 0; bufferID < descCount - 1u; bufferID++)
521 		{
522 			updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bufferID), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageInfos[0]);
523 		}
524 
525 		updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descCount - 1u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageInfos[1]);
526 	}
527 
528 	if (m_params.m_testType == TestType::UniformBuffers)
529 	{
530 		for (deUint32 bufferID = 0; bufferID < descCount - 1u; bufferID++)
531 		{
532 			updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bufferID), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uboInfos[0]);
533 		}
534 
535 		updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descCount - 1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uboInfos[1]);
536 	}
537 
538 	if (m_params.m_testType == TestType::StorageBuffers)
539 	{
540 		for (deUint32 bufferID = 0; bufferID < (descCount - 1u); bufferID++)
541 		{
542 			updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bufferID), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &ssboInfos[0]);
543 		}
544 
545 		updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descCount - 1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &ssboInfos[1]);
546 	}
547 
548 	if (m_params.m_testType == TestType::SampledImages)
549 	{
550 		for (deUint32 bufferID = 0; bufferID < descCount - 1u; bufferID++)
551 		{
552 			updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bufferID), VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfos[0]);
553 		}
554 
555 		updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descCount - 1u), VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfos[1]);
556 	}
557 
558 	if (m_params.m_testType == TestType::StorageImages)
559 	{
560 		for (deUint32 bufferID = 0; bufferID < descCount - 1u; bufferID++)
561 		{
562 			updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bufferID), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageInfos[0]);
563 		}
564 
565 		updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descCount - 1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageInfos[1]);
566 	}
567 
568 	if (m_params.m_testType == TestType::InputAttachments)
569 	{
570 		for (deUint32 bufferID = 0; bufferID < descCount - 1u; bufferID++)
571 		{
572 			updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bufferID), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &imageInfos[0]);
573 		}
574 
575 		updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descCount - 1u), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &imageInfos[1]);
576 	}
577 
578 	updateBuilder.update(vk, vkDevice);
579 
580 	// Create pipeline layout
581 	std::vector<VkDescriptorSetLayout>		descSetLayouts							= { descriptorSetLayout.get() };
582 
583 	if (m_params.m_useCompShader)
584 	{
585 		descSetLayouts.push_back(descriptorSetLayoutResult.get());
586 	}
587 
588 	const VkPipelineLayoutCreateInfo		pipelineLayoutInfo						=
589 	{
590 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	// VkStructureType				sType;
591 		DE_NULL,										// const void*					pNext;
592 		0u,												// VkPipelineLayoutCreateFlags	flags;
593 		static_cast<deUint32>(descSetLayouts.size()),	// deUint32						descriptorSetCount;
594 		descSetLayouts.data(),							// const VkDescriptorSetLayout*	pSetLayouts;
595 		0u,												// deUint32						pushConstantRangeCount;
596 		DE_NULL											// const VkPushDescriptorRange*	pPushDescriptorRanges;
597 	};
598 
599 	const Move<VkPipelineLayout>			pipelineLayout							= createPipelineLayout(vk, vkDevice, &pipelineLayoutInfo);
600 	Move<VkPipeline>						computePipeline							{};
601 	GraphicsPipelineWrapper					graphicsPipelineWrapper					{ vk, vkDevice, m_params.m_pipelineConstructionType };
602 
603 	if (m_params.m_useCompShader)
604 	{
605 		computePipeline = (makeComputePipeline(vk, vkDevice, pipelineLayout.get(), testedShaderModule.get()));
606 	}
607 	else
608 	{
609 		const std::vector<VkViewport>	viewports	{ makeViewport(m_params.m_framebufferSize) };
610 		const std::vector<VkRect2D>		scissors	{ makeRect2D(m_params.m_framebufferSize) };
611 		VkSampleMask					sampleMask	= 0x1;
612 
613 		const VkPipelineMultisampleStateCreateInfo	multisampleStateCreateInfo
614 		{
615 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType
616 			DE_NULL,													// const void*								pNext
617 			0u,															// VkPipelineMultisampleStateCreateFlags	flags
618 			VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples
619 			DE_FALSE,													// VkBool32									sampleShadingEnable
620 			0.0f,														// float									minSampleShading
621 			&sampleMask,												// const VkSampleMask*						pSampleMask
622 			DE_FALSE,													// VkBool32									alphaToCoverageEnable
623 			DE_FALSE,													// VkBool32									alphaToOneEnable
624 		};
625 
626 		graphicsPipelineWrapper.setDefaultDepthStencilState()
627 			.setDefaultColorBlendState()
628 			.setDefaultRasterizationState()
629 			.setupVertexInputState()
630 			.setupPreRasterizationShaderState(viewports,
631 				scissors,
632 				pipelineLayout.get(),
633 				renderPass.get(),
634 				0u,
635 				vertexShaderModule.get())
636 			.setupFragmentShaderState(pipelineLayout.get(),
637 				renderPass.get(),
638 				0u,
639 				testedShaderModule.get(),
640 				DE_NULL,
641 				&multisampleStateCreateInfo)
642 			.setupFragmentOutputState(renderPass.get(), 0u, DE_NULL, &multisampleStateCreateInfo)
643 			.setMonolithicPipelineLayout(pipelineLayout.get())
644 			.buildPipeline();
645 	}
646 
647 	beginCommandBuffer(vk, *cmdBuffer);
648 
649 	if (m_params.m_useCompShader)
650 	{
651 		const std::vector<VkDescriptorSet> descSets = { descriptorSet.get(), descriptorSetResult.get() };
652 
653 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline.get());
654 		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, static_cast<deUint32>(descSets.size()), descSets.data(), 0u, DE_NULL);
655 		vk.cmdDispatch(*cmdBuffer, 1u, 1u, 1u);
656 	}
657 	else
658 	{
659 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, m_params.m_framebufferSize.x(), m_params.m_framebufferSize.y()), static_cast<deUint32>(clearColorValues.size()), clearColorValues.data());
660 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipelineWrapper.getPipeline());
661 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
662 		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
663 		vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
664 		endRenderPass(vk, *cmdBuffer);
665 		copyImageToBuffer(vk, *cmdBuffer, *colorImage, *resultImageBuffer, m_params.m_framebufferSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
666 	}
667 
668 	endCommandBuffer(vk, *cmdBuffer);
669 
670 	submitCommandsAndWait(vk, vkDevice, queue, *cmdBuffer);
671 
672 	// Check results
673 	if (!m_params.m_useCompShader)
674 	{
675 		invalidateAlloc(vk, vkDevice, *resultImageBufferAlloc);
676 
677 		const tcu::ConstPixelBufferAccess	imagePixelAccess	(mapVkFormat(colorFormat), m_params.m_framebufferSize.x(), m_params.m_framebufferSize.y(), 1, resultImageBufferAlloc->getHostPtr());
678 		const tcu::TextureLevel				referenceTexture	= generateColorImage(colorFormat, m_params.m_framebufferSize, testColors[1]);
679 
680 		if (!tcu::floatThresholdCompare(log, "Compare color output", "Image result comparison", referenceTexture.getAccess(), imagePixelAccess, tcu::Vec4(0.0f), tcu::COMPARE_LOG_RESULT))
681 			return tcu::TestStatus::fail("Rendered color image is not correct");
682 	}
683 	else
684 	{
685 		invalidateAlloc(vk, vkDevice, *ssboBufferAllocResult);
686 		const tcu::Vec4	resultValue	= *static_cast<tcu::Vec4*>(ssboBufferAllocResult->getHostPtr());
687 
688 		if (!(resultValue == tcu::Vec4(0.0, 1.0, 0.0, 1.0)))
689 			return tcu::TestStatus::fail("Result buffer value is not correct");
690 	}
691 
692 	return tcu::TestStatus::pass("Success");
693 }
694 
695 class DescriptorLimitTest : public vkt::TestCase
696 {
697 public:
DescriptorLimitTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const TestParams & params)698 							DescriptorLimitTest		(tcu::TestContext&				testContext,
699 													 const std::string&				name,
700 													 const std::string&				description,
701 													 const TestParams&				params)
702 							: TestCase(testContext, name, description)
703 							, m_params						(params)
704 							{}
705 
~DescriptorLimitTest(void)706 	virtual					~DescriptorLimitTest	(void)
707 							{}
708 
709 	virtual void			initPrograms			(SourceCollections& programCollection) const;
710 	virtual void			checkSupport			(Context& context) const;
711 	virtual TestInstance*	createInstance			(Context& context) const;
712 
713 private:
714 	TestParams	m_params;
715 };
716 
initPrograms(SourceCollections & sourceCollections) const717 void DescriptorLimitTest::initPrograms (SourceCollections& sourceCollections) const
718 {
719 	std::ostringstream	testTypeStr;
720 	std::ostringstream	fragResultStr;
721 	std::ostringstream	compResultStr;
722 	const deUint32		descCount		= m_params.getDescCount();
723 
724 	if (m_params.m_testType == TestType::Samplers)
725 	{
726 		testTypeStr		<< "layout(set = 0, binding = " << descCount - 1u << ") uniform sampler2D texSamplerInput;\n";
727 
728 		fragResultStr	<<	"    const vec2 coords = vec2(0, 0);\n"
729 						<<	"    fragColor = texture(texSamplerInput, coords);\n";
730 
731 		compResultStr	<<	"    const vec2 coords = vec2(0, 0);\n"
732 						<<	"    outputData.color = texture(texSamplerInput, coords);\n";
733 	}
734 
735 	if (m_params.m_testType == TestType::UniformBuffers)
736 	{
737 		testTypeStr		<< "layout(set = 0, binding = " << descCount - 1u << ") uniform uboInput\n"
738 						<< "{\n"
739 						<< "    vec4 color;\n"
740 						<< "} inputData;\n"
741 						<< "\n";
742 
743 		fragResultStr	<< "    fragColor = inputData.color;\n";
744 		compResultStr	<< "    outputData.color = inputData.color;\n";
745 	}
746 
747 	if (m_params.m_testType == TestType::StorageBuffers)
748 	{
749 		testTypeStr		<< "layout(set = 0, binding = " << (descCount - 1u) << ") readonly buffer ssboInput\n"
750 						<< "{\n"
751 						<< "    vec4 color;\n"
752 						<< "} inputData;\n"
753 						<< "\n";
754 
755 		fragResultStr	<< "    fragColor = inputData.color;\n";
756 		compResultStr	<< "    outputData.color = inputData.color;\n";
757 	}
758 
759 	if (m_params.m_testType == TestType::SampledImages)
760 	{
761 		testTypeStr		<< "#extension GL_EXT_samplerless_texture_functions : enable\n"
762 						<< "layout(set = 0, binding = " << descCount - 1u << ") uniform texture2D imageInput;\n";
763 
764 		fragResultStr	<< "    fragColor = texelFetch(imageInput, ivec2(gl_FragCoord.xy), 0);\n";
765 		compResultStr	<< "    const ivec2 coords = ivec2(0, 0);\n"
766 						<< "    outputData.color = texelFetch(imageInput, coords, 0);\n";
767 	}
768 
769 	if (m_params.m_testType == TestType::StorageImages)
770 	{
771 		testTypeStr		<< "#extension GL_EXT_samplerless_texture_functions : enable\n"
772 						<< "layout(set = 0, binding = " << descCount - 1u << ", rgba8) uniform image2D imageInput;\n";
773 
774 		fragResultStr	<< "    fragColor = imageLoad(imageInput, ivec2(gl_FragCoord.xy));\n";
775 		compResultStr	<< "    const ivec2 coords = ivec2(0, 0);\n"
776 						<< "    outputData.color = imageLoad(imageInput, coords);\n";
777 	}
778 
779 	if (m_params.m_testType == TestType::InputAttachments)
780 	{
781 		testTypeStr << "layout (input_attachment_index = 1, set = 0, binding = " << descCount - 1u << ") uniform subpassInput imageInput;\n";
782 
783 		fragResultStr	<< "    fragColor = subpassLoad(imageInput);\n";
784 		compResultStr	<< "    outputData.color = vec4(0.0, 0.0, 0.0, 1.0);\n";
785 	}
786 
787 	std::ostringstream vertexSrc;
788 	vertexSrc	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
789 				<< "\n"
790 				<< "layout(location = 0) in vec4 position;\n"
791 				<< "\n"
792 				<< "void main (void)\n"
793 				<< "{\n"
794 				<< "    gl_Position = position;\n"
795 				<< "}\n";
796 
797 	sourceCollections.glslSources.add("vert") << glu::VertexSource(vertexSrc.str());
798 
799 	std::ostringstream testSrc;
800 
801 	if (!m_params.m_useCompShader)
802 	{
803 		testSrc << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
804 			<< "\n"
805 			<< "layout(location = 0) out vec4 fragColor;\n"
806 			<< "\n"
807 			<< testTypeStr.str()
808 			<< "void main (void)\n"
809 			<< "{\n"
810 			<< fragResultStr.str()
811 			<< "}\n";
812 
813 		sourceCollections.glslSources.add("test") << glu::FragmentSource(testSrc.str());
814 	}
815 	else
816 	{
817 		testSrc	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
818 				<< "\n"
819 				// Input attachments are not supported by compute shaders.
820 				<< (m_params.m_testType != TestType::InputAttachments ? testTypeStr.str() : "")
821 				<< "layout(set = 1, binding = 0) buffer ssboOutput\n"
822 				<< "{\n"
823 				<< "    vec4 color;\n"
824 				<< "} outputData;\n"
825 				<< "\n"
826 				<< "void main (void)\n"
827 				<< "{\n"
828 				<< compResultStr.str()
829 				<< "}\n";
830 
831 		sourceCollections.glslSources.add("test") << glu::ComputeSource(testSrc.str());
832 	}
833 }
834 
checkSupport(Context & context) const835 void DescriptorLimitTest::checkSupport (Context& context) const
836 {
837 	const InstanceInterface&		vki				= context.getInstanceInterface();
838 	const VkPhysicalDevice			physDevice		= context.getPhysicalDevice();
839 	const VkPhysicalDeviceLimits	limits			= getPhysicalDeviceProperties(vki, physDevice).limits;
840 
841 	// We have to make sure, that we don't bind anything outside of valid descriptor binding locations determined by maxPerStageResources.
842 	if (m_params.m_descCount > limits.maxPerStageResources - 1u)
843 		TCU_THROW(NotSupportedError, "maxPerStageResources (" + std::to_string(limits.maxPerStageResources) + ")");
844 
845 	if (m_params.m_testType == TestType::Samplers)
846 	{
847 		if(m_params.m_descCount > limits.maxPerStageDescriptorSamplers)
848 			TCU_THROW(NotSupportedError, "maxPerStageDescriptorSamplers (" + std::to_string(limits.maxPerStageDescriptorSamplers) + ")");
849 	}
850 
851 	if (m_params.m_testType == TestType::UniformBuffers)
852 	{
853 		if (m_params.m_descCount > limits.maxPerStageDescriptorUniformBuffers)
854 			TCU_THROW(NotSupportedError, "maxPerStageDescriptorUniformBuffers (" + std::to_string(limits.maxPerStageDescriptorUniformBuffers) + ")");
855 	}
856 
857 	if (m_params.m_testType == TestType::StorageBuffers)
858 	{
859 		if (m_params.m_descCount > limits.maxPerStageDescriptorStorageBuffers)
860 			TCU_THROW(NotSupportedError, "maxPerStageDescriptorStorageBuffers (" + std::to_string(limits.maxPerStageDescriptorStorageBuffers) + ")");
861 	}
862 
863 	if (m_params.m_testType == TestType::SampledImages)
864 	{
865 		if (m_params.m_descCount > limits.maxPerStageDescriptorSampledImages)
866 			TCU_THROW(NotSupportedError, "maxPerStageDescriptorSampledImages (" + std::to_string(limits.maxPerStageDescriptorSampledImages) + ")");
867 	}
868 
869 	if (m_params.m_testType == TestType::StorageImages)
870 	{
871 		if (m_params.m_descCount > limits.maxPerStageDescriptorStorageImages)
872 			TCU_THROW(NotSupportedError, "maxPerStageDescriptorStorageImages (" + std::to_string(limits.maxPerStageDescriptorStorageImages) + ")");
873 	}
874 
875 	if (m_params.m_testType == TestType::InputAttachments)
876 	{
877 		if (m_params.m_descCount > limits.maxPerStageDescriptorInputAttachments)
878 			TCU_THROW(NotSupportedError, "maxPerStageDescriptorInputAttachments (" + std::to_string(limits.maxPerStageDescriptorInputAttachments) + ")");
879 	}
880 
881 	checkPipelineLibraryRequirements(vki, physDevice, m_params.m_pipelineConstructionType);
882 }
883 
createInstance(Context & context) const884 TestInstance* DescriptorLimitTest::createInstance (Context& context) const
885 {
886 	return new DescriptorLimitTestInstance(context, m_params);
887 }
888 
889 }
890 
createDescriptorLimitsTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)891 tcu::TestCaseGroup* createDescriptorLimitsTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
892 {
893 	de::MovePtr<tcu::TestCaseGroup>	descriptorLimitTestGroup	(new tcu::TestCaseGroup(testCtx, "descriptor_limits", "Descriptor limits tests"));
894 	const tcu::IVec2				frameBufferSize				= tcu::IVec2(32, 32);
895 
896 	const std::vector<deUint32>		numDescriptors				=
897 	{
898 		3u,		4u,		5u,		6u,		7u,		8u,		9u,		10u,	11u,
899 		12u,	13u,	14u,	15u,	16u,	17u,	18u,	19u,	20u,
900 		31u,	32u,	63u,	64u,	100u,	127u,	128u,	199u,	200u,
901 		256u,	512u,	1024u,	2048u,	4096u,	8192u,	16384u,	32768u,	65535u
902 	};
903 
904 	if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
905 	{
906 		de::MovePtr<tcu::TestCaseGroup>	computeShaderGroup(new tcu::TestCaseGroup(testCtx, "compute_shader", "Compute shader test group"));
907 
908 		for (const auto& descId : numDescriptors)
909 		{
910 			const deUint32	testValue		= descId;
911 
912 			{
913 				TestParams params(pipelineConstructionType, TestType::Samplers, true, frameBufferSize, testValue);
914 				computeShaderGroup->addChild(new DescriptorLimitTest(testCtx, "samplers_" + std::to_string(testValue), "", params));
915 			}
916 
917 			{
918 				TestParams params(pipelineConstructionType, TestType::UniformBuffers, true, frameBufferSize, testValue);
919 				computeShaderGroup->addChild(new DescriptorLimitTest(testCtx, "uniform_buffers_" + std::to_string(testValue), "", params));
920 			}
921 
922 			{
923 				TestParams params(pipelineConstructionType, TestType::StorageBuffers, true, frameBufferSize, testValue);
924 				computeShaderGroup->addChild(new DescriptorLimitTest(testCtx, "storage_buffers_" + std::to_string(testValue), "", params));
925 			}
926 
927 			{
928 				TestParams params(pipelineConstructionType, TestType::SampledImages, true, frameBufferSize, testValue);
929 				computeShaderGroup->addChild(new DescriptorLimitTest(testCtx, "sampled_images_" + std::to_string(testValue), "", params));
930 			}
931 
932 			{
933 				TestParams params(pipelineConstructionType, TestType::StorageImages, true, frameBufferSize, testValue);
934 				computeShaderGroup->addChild(new DescriptorLimitTest(testCtx, "storage_images_" + std::to_string(testValue), "", params));
935 			}
936 		}
937 
938 		descriptorLimitTestGroup->addChild(computeShaderGroup.release());
939 	}
940 
941 	de::MovePtr<tcu::TestCaseGroup>	fragmentShaderGroup(new tcu::TestCaseGroup(testCtx, "fragment_shader", "Fragment shader test group"));
942 
943 	for (const auto& descId : numDescriptors)
944 	{
945 		const deUint32	testValue	= descId;
946 
947 		{
948 			TestParams params(pipelineConstructionType, TestType::Samplers, false, frameBufferSize, testValue);
949 			fragmentShaderGroup->addChild(new DescriptorLimitTest(testCtx, "samplers_" + std::to_string(testValue), "", params));
950 		}
951 
952 		{
953 			TestParams params(pipelineConstructionType, TestType::UniformBuffers, false, frameBufferSize, testValue);
954 			fragmentShaderGroup->addChild(new DescriptorLimitTest(testCtx, "uniform_buffers_" + std::to_string(testValue), "", params));
955 		}
956 
957 		{
958 			TestParams params(pipelineConstructionType, TestType::StorageBuffers, false, frameBufferSize, testValue);
959 			fragmentShaderGroup->addChild(new DescriptorLimitTest(testCtx, "storage_buffers_" + std::to_string(testValue), "", params));
960 		}
961 
962 		{
963 			TestParams params(pipelineConstructionType, TestType::SampledImages, false, frameBufferSize, testValue);
964 			fragmentShaderGroup->addChild(new DescriptorLimitTest(testCtx, "sampled_images_" + std::to_string(testValue), "", params));
965 		}
966 
967 		{
968 			TestParams params(pipelineConstructionType, TestType::StorageImages, false, frameBufferSize, testValue);
969 			fragmentShaderGroup->addChild(new DescriptorLimitTest(testCtx, "storage_images_" + std::to_string(testValue), "", params));
970 		}
971 
972 		{
973 			TestParams params(pipelineConstructionType, TestType::InputAttachments, false, frameBufferSize, testValue);
974 			fragmentShaderGroup->addChild(new DescriptorLimitTest(testCtx, "input_attachments_" + std::to_string(testValue), "", params));
975 		}
976 	}
977 
978 	descriptorLimitTestGroup->addChild(fragmentShaderGroup.release());
979 
980 	return descriptorLimitTestGroup.release();
981 }
982 
983 } // pipeline
984 } // vkt
985