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
46namespace vkt
47{
48namespace pipeline
49{
50
51using namespace vk;
52
53namespace
54{
55
56enum class TestType
57{
58	Samplers			= 0,
59	UniformBuffers		= 1,
60	StorageBuffers		= 2,
61	SampledImages		= 3,
62	StorageImages		= 4,
63	InputAttachments	= 5
64};
65
66inline 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
89tcu::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
97RenderPassWrapper 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
164struct TestParams
165{
166	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
184	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
195class DescriptorLimitTestInstance : public vkt::TestInstance
196{
197public:
198							DescriptorLimitTestInstance		(Context&						context,
199															const TestParams&				params)
200															: vkt::TestInstance				(context)
201															, m_params						(params)
202							{}
203
204							~DescriptorLimitTestInstance	()
205							{}
206
207	virtual tcu::TestStatus	iterate							(void);
208
209private:
210	struct BufferInfo
211	{
212		tcu::Vec4	color;
213	};
214	TestParams	m_params;
215};
216
217tcu::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
705class DescriptorLimitTest : public vkt::TestCase
706{
707public:
708							DescriptorLimitTest		(tcu::TestContext&				testContext,
709													 const std::string&				name,
710													 const TestParams&				params)
711							: TestCase(testContext, name)
712							, m_params						(params)
713							{}
714
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
722private:
723	TestParams	m_params;
724};
725
726void 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
844void 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
893TestInstance* DescriptorLimitTest::createInstance (Context& context) const
894{
895	return new DescriptorLimitTestInstance(context, m_params);
896}
897
898}
899
900tcu::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