1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 The Khronos Group Inc.
6  * Copyright (c) 2018 Google Inc.
7  * Copyright (c) 2015 Imagination Technologies Ltd.
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Tests sparse input attachments in VkSubpassDescription::pInputAttachments
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktRenderPassUnusedAttachmentSparseFillingTests.hpp"
27 #include "vktTestCase.hpp"
28 #include "vkImageUtil.hpp"
29 #include "vkBuilderUtil.hpp"
30 #include "vkQueryUtil.hpp"
31 #include "vkCmdUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "tcuTestLog.hpp"
34 #include "deRandom.hpp"
35 #include <sstream>
36 #include <vector>
37 #include <algorithm>
38 #include <numeric>
39 #include <random>
40 
41 typedef de::SharedPtr<vk::Unique<vk::VkImage> >		VkImageSp;
42 typedef de::SharedPtr<vk::Unique<vk::VkImageView> >	VkImageViewSp;
43 typedef de::SharedPtr<vk::Unique<vk::VkBuffer> >	VkBufferSp;
44 typedef de::SharedPtr<vk::Allocation>				AllocationSp;
45 
46 namespace vkt
47 {
48 
49 namespace renderpass
50 {
51 
52 using namespace vk;
53 
54 template<typename T>
safeSharedPtr(T * ptr)55 de::SharedPtr<T> safeSharedPtr(T* ptr)
56 {
57 	try
58 	{
59 		return de::SharedPtr<T>(ptr);
60 	}
61 	catch (...)
62 	{
63 		delete ptr;
64 		throw;
65 	}
66 }
67 
68 static const deUint32		RENDER_SIZE		= 8u;
69 static const unsigned int	DEFAULT_SEED	= 31u;
70 
71 namespace
72 {
73 
74 struct TestParams
75 {
76 	RenderPassType		renderPassType;
77 	deUint32			activeInputAttachmentCount;
78 };
79 
80 struct Vertex
81 {
82 	tcu::Vec4 position;
83 	tcu::Vec4 uv;
84 };
85 
createFullscreenTriangle(void)86 std::vector<Vertex> createFullscreenTriangle (void)
87 {
88 	std::vector<Vertex>	vertices;
89 
90 	for (deUint32 i = 0; i < 3; ++i)
91 	{
92 		float x = static_cast<float>((i << 1) & 2);
93 		float y = static_cast<float>(i & 2);
94 		vertices.push_back(Vertex{ tcu::Vec4(x * 2.0f - 1.0f, y * 2.0f - 1.0f, 0.0f, 1.0f), tcu::Vec4(x,y,0.0f,0.0f) });
95 	}
96 	return vertices;
97 }
98 
generateInputAttachmentParams(deUint32 activeAttachmentCount,deUint32 allAttachmentCount,std::vector<deUint32> & attachmentIndices,std::vector<deUint32> & descriptorBindings)99 void generateInputAttachmentParams(deUint32 activeAttachmentCount, deUint32 allAttachmentCount, std::vector<deUint32>& attachmentIndices, std::vector<deUint32>& descriptorBindings)
100 {
101 	attachmentIndices.resize(allAttachmentCount);
102 	std::iota(begin(attachmentIndices), begin(attachmentIndices) + activeAttachmentCount, 0);
103 	std::fill(begin(attachmentIndices) + activeAttachmentCount, end(attachmentIndices), VK_ATTACHMENT_UNUSED);
104 	de::Random random(DEFAULT_SEED);
105 	random.shuffle(begin(attachmentIndices), end(attachmentIndices));
106 
107 	descriptorBindings.resize(activeAttachmentCount+1);
108 	descriptorBindings[0] = VK_ATTACHMENT_UNUSED;
109 	for (deUint32 i = 0, lastBinding = 1; i < allAttachmentCount; ++i)
110 	{
111 		if (attachmentIndices[i] != VK_ATTACHMENT_UNUSED)
112 			descriptorBindings[lastBinding++] = i;
113 	}
114 }
115 
116 class InputAttachmentSparseFillingTest : public vkt::TestCase
117 {
118 public:
119 										InputAttachmentSparseFillingTest	(tcu::TestContext&	testContext,
120 																			 const std::string&	name,
121 																			 const std::string&	description,
122 																			 const TestParams&	testParams);
123 	virtual								~InputAttachmentSparseFillingTest	(void);
124 	virtual void						initPrograms						(SourceCollections&	sourceCollections) const;
125 	virtual TestInstance*				createInstance						(Context&			context) const;
126 	virtual void						checkSupport						(Context& context) const;
127 
128 private:
129 	TestParams m_testParams;
130 };
131 
132 class InputAttachmentSparseFillingTestInstance : public vkt::TestInstance
133 {
134 public:
135 										InputAttachmentSparseFillingTestInstance	(Context&			context,
136 																					 const TestParams&	testParams);
137 	virtual								~InputAttachmentSparseFillingTestInstance	(void);
138 	virtual tcu::TestStatus				iterate										(void);
139 	template<typename RenderpassSubpass>
140 	void								createCommandBuffer							(const DeviceInterface&	vk,
141 																					 VkDevice				vkDevice);
142 
143 	template<typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep, typename RenderPassCreateInfo>
144 	Move<VkRenderPass>					createRenderPass							(const DeviceInterface&	vk,
145 																					 VkDevice				vkDevice);
146 private:
147 	tcu::TestStatus						verifyImage									(void);
148 
149 	const tcu::UVec2					m_renderSize;
150 	std::vector<Vertex>					m_vertices;
151 	TestParams							m_testParams;
152 
153 	std::vector<VkImageSp>				m_inputImages;
154 	std::vector<AllocationSp>			m_inputImageMemory;
155 	std::vector<VkImageViewSp>			m_inputImageViews;
156 
157 	VkImageSp							m_outputImage;
158 	AllocationSp						m_outputImageMemory;
159 	VkImageViewSp						m_outputImageView;
160 
161 	VkBufferSp							m_outputBuffer;
162 	AllocationSp						m_outputBufferMemory;
163 
164 	Move<VkDescriptorSetLayout>			m_descriptorSetLayout;
165 	Move<VkDescriptorPool>				m_descriptorPool;
166 	Move<VkDescriptorSet>				m_descriptorSet;
167 	Move<VkRenderPass>					m_renderPass;
168 	Move<VkFramebuffer>					m_framebuffer;
169 
170 	Move<VkShaderModule>				m_vertexShaderModule;
171 	Move<VkShaderModule>				m_fragmentShaderModule;
172 
173 	Move<VkBuffer>						m_vertexBuffer;
174 	de::MovePtr<Allocation>				m_vertexBufferAlloc;
175 
176 	Move<VkPipelineLayout>				m_pipelineLayout;
177 	Move<VkPipeline>					m_graphicsPipeline;
178 
179 	Move<VkCommandPool>					m_cmdPool;
180 	Move<VkCommandBuffer>				m_cmdBuffer;
181 };
182 
InputAttachmentSparseFillingTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const TestParams & testParams)183 InputAttachmentSparseFillingTest::InputAttachmentSparseFillingTest (tcu::TestContext&	testContext,
184 																	const std::string&	name,
185 																	const std::string&	description,
186 																	const TestParams&	testParams)
187 	: vkt::TestCase	(testContext, name, description), m_testParams(testParams)
188 {
189 }
190 
~InputAttachmentSparseFillingTest(void)191 InputAttachmentSparseFillingTest::~InputAttachmentSparseFillingTest	(void)
192 {
193 }
194 
initPrograms(SourceCollections & sourceCollections) const195 void InputAttachmentSparseFillingTest::initPrograms (SourceCollections& sourceCollections) const
196 {
197 	std::ostringstream fragmentSource;
198 
199 	sourceCollections.glslSources.add("vertex") << glu::VertexSource(
200 		"#version 450\n"
201 		"layout(location = 0) in vec4 position;\n"
202 		"layout(location = 1) in vec4 uv;\n"
203 		"layout(location = 0) out vec4 outUV;\n"
204 		"void main (void)\n"
205 		"{\n"
206 		"	gl_Position = position;\n"
207 		"	outUV = uv;\n"
208 		"}\n");
209 
210 	// We read from X input attachments randomly spread in input attachment array of size 2*X
211 	std::ostringstream str;
212 	str	<< "#version 450\n"
213 		<< "layout(location = 0) in vec4 inUV;\n"
214 		<< "layout(binding = 0, rg32ui) uniform uimage2D resultImage;\n";
215 
216 	std::vector<deUint32> attachmentIndices, descriptorBindings;
217 	generateInputAttachmentParams(m_testParams.activeInputAttachmentCount, 2u * m_testParams.activeInputAttachmentCount, attachmentIndices, descriptorBindings);
218 
219 	for (std::size_t i = 1; i < descriptorBindings.size(); ++i)
220 		str << "layout(binding = " << i << ", input_attachment_index = " << descriptorBindings[i] <<") uniform subpassInput attach" << i <<";\n";
221 
222 	str << "void main (void)\n"
223 		<< "{\n"
224 		<< "	uvec4 result = uvec4(0);\n";
225 
226 	for (std::size_t i = 1; i < descriptorBindings.size(); ++i)
227 	{
228 		str << "	result.x = result.x + 1;\n";
229 		str << "	if(subpassLoad(attach" << i << ").x > 0.0)\n";
230 		str << "		result.y = result.y + 1;\n";
231 	}
232 
233 	str	<< "	imageStore(resultImage, ivec2(imageSize(resultImage) * inUV.xy), result);\n"
234 		<< "}\n";
235 
236 	sourceCollections.glslSources.add("fragment") << glu::FragmentSource(str.str());
237 }
238 
createInstance(Context & context) const239 TestInstance* InputAttachmentSparseFillingTest::createInstance(Context& context) const
240 {
241 	return new InputAttachmentSparseFillingTestInstance(context, m_testParams);
242 }
243 
checkSupport(Context & context) const244 void InputAttachmentSparseFillingTest::checkSupport(Context& context) const
245 {
246 	if (m_testParams.renderPassType == RENDERPASS_TYPE_RENDERPASS2)
247 		context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
248 
249 	const vk::VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(context.getInstanceInterface(), context.getPhysicalDevice()).limits;
250 
251 	if( 2u * m_testParams.activeInputAttachmentCount > limits.maxPerStageDescriptorInputAttachments )
252 		TCU_THROW(NotSupportedError, "Input attachment count including unused elements exceeds maxPerStageDescriptorInputAttachments");
253 
254 	if ( 2u * m_testParams.activeInputAttachmentCount > limits.maxPerStageResources)
255 		TCU_THROW(NotSupportedError, "Input attachment count including unused elements exceeds maxPerStageResources");
256 }
257 
InputAttachmentSparseFillingTestInstance(Context & context,const TestParams & testParams)258 InputAttachmentSparseFillingTestInstance::InputAttachmentSparseFillingTestInstance (Context& context, const TestParams& testParams)
259 	: vkt::TestInstance	(context)
260 	, m_renderSize		(RENDER_SIZE, RENDER_SIZE)
261 	, m_vertices		(createFullscreenTriangle())
262 	, m_testParams		(testParams)
263 {
264 	const DeviceInterface&				vk						= m_context.getDeviceInterface();
265 	const VkDevice						vkDevice				= m_context.getDevice();
266 	const deUint32						queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
267 	SimpleAllocator						memAlloc				(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
268 	const VkComponentMapping			componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
269 
270 	{
271 		const VkImageCreateInfo	inputImageParams =
272 		{
273 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,									// VkStructureType			sType;
274 			DE_NULL,																// const void*				pNext;
275 			0u,																		// VkImageCreateFlags		flags;
276 			VK_IMAGE_TYPE_2D,														// VkImageType				imageType;
277 			VK_FORMAT_R8G8B8A8_UNORM,												// VkFormat					format;
278 			{ m_renderSize.x(), m_renderSize.y(), 1u },								// VkExtent3D				extent;
279 			1u,																		// deUint32					mipLevels;
280 			1u,																		// deUint32					arrayLayers;
281 			VK_SAMPLE_COUNT_1_BIT,													// VkSampleCountFlagBits	samples;
282 			VK_IMAGE_TILING_OPTIMAL,												// VkImageTiling			tiling;
283 			VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,	// VkImageUsageFlags		usage;
284 			VK_SHARING_MODE_EXCLUSIVE,												// VkSharingMode			sharingMode;
285 			1u,																		// deUint32					queueFamilyIndexCount;
286 			&queueFamilyIndex,														// const deUint32*			pQueueFamilyIndices;
287 			VK_IMAGE_LAYOUT_UNDEFINED												// VkImageLayout			initialLayout;
288 		};
289 
290 		VkImageViewCreateInfo inputAttachmentViewParams =
291 		{
292 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,								// VkStructureType			sType;
293 			DE_NULL,																// const void*				pNext;
294 			0u,																		// VkImageViewCreateFlags	flags;
295 			0,																		// VkImage					image;
296 			VK_IMAGE_VIEW_TYPE_2D,													// VkImageViewType			viewType;
297 			VK_FORMAT_R8G8B8A8_UNORM,												// VkFormat					format;
298 			componentMappingRGBA,													// VkChannelMapping			channels;
299 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }							// VkImageSubresourceRange	subresourceRange;
300 		};
301 
302 		// Create input attachment images with image views
303 		for (deUint32 imageNdx = 0; imageNdx < m_testParams.activeInputAttachmentCount; ++imageNdx)
304 		{
305 			auto inputImage					= safeSharedPtr(new Unique<VkImage>(vk::createImage(vk, vkDevice, &inputImageParams)));
306 
307 			auto inputImageAlloc			= safeSharedPtr(memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, **inputImage), MemoryRequirement::Any).release());
308 			VK_CHECK(vk.bindImageMemory(vkDevice, **inputImage, inputImageAlloc->getMemory(), inputImageAlloc->getOffset()));
309 
310 			inputAttachmentViewParams.image	= **inputImage;
311 			auto inputImageView				= safeSharedPtr(new Unique<VkImageView>(createImageView(vk, vkDevice, &inputAttachmentViewParams)));
312 
313 			m_inputImages.push_back(inputImage);
314 			m_inputImageMemory.push_back(inputImageAlloc);
315 			m_inputImageViews.push_back(inputImageView);
316 		}
317 	}
318 
319 	{
320 		const VkImageCreateInfo	outputImageParams =
321 		{
322 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,									// VkStructureType			sType;
323 			DE_NULL,																// const void*				pNext;
324 			0u,																		// VkImageCreateFlags		flags;
325 			VK_IMAGE_TYPE_2D,														// VkImageType				imageType;
326 			VK_FORMAT_R32G32_UINT,													// VkFormat					format;
327 			{ m_renderSize.x(), m_renderSize.y(), 1u },								// VkExtent3D				extent;
328 			1u,																		// deUint32					mipLevels;
329 			1u,																		// deUint32					arrayLayers;
330 			VK_SAMPLE_COUNT_1_BIT,													// VkSampleCountFlagBits	samples;
331 			VK_IMAGE_TILING_OPTIMAL,												// VkImageTiling			tiling;
332 			VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
333 				VK_IMAGE_USAGE_TRANSFER_DST_BIT,									// VkImageUsageFlags		usage;
334 			VK_SHARING_MODE_EXCLUSIVE,												// VkSharingMode			sharingMode;
335 			1u,																		// deUint32					queueFamilyIndexCount;
336 			&queueFamilyIndex,														// const deUint32*			pQueueFamilyIndices;
337 			VK_IMAGE_LAYOUT_UNDEFINED												// VkImageLayout			initialLayout;
338 		};
339 
340 		m_outputImage		= safeSharedPtr(new Unique<VkImage>(vk::createImage(vk, vkDevice, &outputImageParams)));
341 		m_outputImageMemory = safeSharedPtr(memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, **m_outputImage), MemoryRequirement::Any).release());
342 		VK_CHECK(vk.bindImageMemory(vkDevice, **m_outputImage, m_outputImageMemory->getMemory(), m_outputImageMemory->getOffset()));
343 
344 		VkImageViewCreateInfo inputAttachmentViewParams =
345 		{
346 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,								// VkStructureType			sType;
347 			DE_NULL,																// const void*				pNext;
348 			0u,																		// VkImageViewCreateFlags	flags;
349 			**m_outputImage,														// VkImage					image;
350 			VK_IMAGE_VIEW_TYPE_2D,													// VkImageViewType			viewType;
351 			VK_FORMAT_R32G32_UINT,													// VkFormat					format;
352 			componentMappingRGBA,													// VkChannelMapping			channels;
353 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }							// VkImageSubresourceRange	subresourceRange;
354 		};
355 		m_outputImageView = safeSharedPtr(new Unique<VkImageView>(createImageView(vk, vkDevice, &inputAttachmentViewParams)));
356 	}
357 
358 	{
359 		const VkDeviceSize			outputBufferSizeBytes	= m_renderSize.x() * m_renderSize.y() * tcu::getPixelSize(mapVkFormat(VK_FORMAT_R32G32_UINT));
360 		const VkBufferCreateInfo	outputBufferParams		=
361 		{
362 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// sType
363 			DE_NULL,									// pNext
364 			(VkBufferCreateFlags)0u,					// flags
365 			outputBufferSizeBytes,						// size
366 			VK_BUFFER_USAGE_TRANSFER_DST_BIT,			// usage
367 			VK_SHARING_MODE_EXCLUSIVE,					// sharingMode
368 			1u,											// queueFamilyIndexCount
369 			&queueFamilyIndex,							// pQueueFamilyIndices
370 		};
371 		m_outputBuffer			= safeSharedPtr(new Unique<VkBuffer>(createBuffer(vk, vkDevice, &outputBufferParams)));
372 		m_outputBufferMemory	= safeSharedPtr(memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, **m_outputBuffer), MemoryRequirement::HostVisible).release());
373 		VK_CHECK(vk.bindBufferMemory(vkDevice, **m_outputBuffer, m_outputBufferMemory->getMemory(), m_outputBufferMemory->getOffset()));
374 	}
375 
376 	// Create render pass
377 	if (testParams.renderPassType == RENDERPASS_TYPE_LEGACY)
378 		m_renderPass = createRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1, SubpassDependency1, RenderPassCreateInfo1>(vk, vkDevice);
379 	else
380 		m_renderPass = createRenderPass<AttachmentDescription2, AttachmentReference2, SubpassDescription2, SubpassDependency2, RenderPassCreateInfo2>(vk, vkDevice);
381 
382 	std::vector<VkDescriptorImageInfo>	descriptorImageInfos;
383 	std::vector<VkImageView> framebufferImageViews;
384 	descriptorImageInfos.push_back(
385 		VkDescriptorImageInfo{
386 			DE_NULL,				// VkSampleri		sampler;
387 			**m_outputImageView,	// VkImageView		imageView;
388 			VK_IMAGE_LAYOUT_GENERAL	// VkImageLayout	imageLayout;
389 		}
390 	);
391 	for (auto& inputImageView : m_inputImageViews)
392 	{
393 		framebufferImageViews.push_back(**inputImageView);
394 		descriptorImageInfos.push_back(
395 			VkDescriptorImageInfo{
396 				DE_NULL,									// VkSampleri		sampler;
397 				**inputImageView,							// VkImageView		imageView;
398 				VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL	// VkImageLayout	imageLayout;
399 			}
400 		);
401 	}
402 
403 	// Create framebuffer
404 	{
405 		const VkFramebufferCreateInfo	framebufferParams	=
406 		{
407 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,				// VkStructureType			sType;
408 			DE_NULL,												// const void*				pNext;
409 			0u,														// VkFramebufferCreateFlags	flags;
410 			*m_renderPass,											// VkRenderPass				renderPass;
411 			static_cast<deUint32>(framebufferImageViews.size()),	// deUint32					attachmentCount;
412 			framebufferImageViews.data(),							// const VkImageView*		pAttachments;
413 			static_cast<deUint32>(m_renderSize.x()),				// deUint32					width;
414 			static_cast<deUint32>(m_renderSize.y()),				// deUint32					height;
415 			1u														// deUint32					layers;
416 		};
417 
418 		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
419 	}
420 
421 	// Create pipeline layout
422 	{
423 		DescriptorSetLayoutBuilder	layoutBuilder;
424 		// add output image storage
425 		layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT);
426 		// add input attachments
427 		for (deUint32 imageNdx = 0; imageNdx < m_testParams.activeInputAttachmentCount; ++imageNdx)
428 			layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT);
429 		m_descriptorSetLayout = layoutBuilder.build(vk, vkDevice);
430 
431 		const VkPipelineLayoutCreateInfo		pipelineLayoutParams		=
432 		{
433 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,			// VkStructureType					sType;
434 			DE_NULL,												// const void*						pNext;
435 			0u,														// VkPipelineLayoutCreateFlags		flags;
436 			1u,														// deUint32							setLayoutCount;
437 			&m_descriptorSetLayout.get(),							// const VkDescriptorSetLayout*		pSetLayouts;
438 			0u,														// deUint32							pushConstantRangeCount;
439 			DE_NULL													// const VkPushConstantRange*		pPushConstantRanges;
440 		};
441 
442 		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
443 	}
444 
445 	// Update descriptor set
446 	{
447 		m_descriptorPool = DescriptorPoolBuilder()
448 			.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,		1u)
449 			.addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,	m_testParams.activeInputAttachmentCount)
450 			.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
451 
452 		const VkDescriptorSetAllocateInfo	descriptorSetAllocateInfo	=
453 		{
454 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,		// VkStructureType					sType
455 			DE_NULL,											// const void*						pNext
456 			*m_descriptorPool,									// VkDescriptorPool					descriptorPool
457 			1u,													// deUint32							descriptorSetCount
458 			&m_descriptorSetLayout.get(),						// const VkDescriptorSetLayout*		pSetLayouts
459 		};
460 		m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
461 
462 		DescriptorSetUpdateBuilder builder;
463 		builder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfos[0]);
464 		for( deUint32 i=1; i<static_cast<deUint32>(descriptorImageInfos.size()); ++i)
465 			builder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(i), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &descriptorImageInfos[i]);
466 		builder.update(vk, vkDevice);
467 	}
468 
469 	m_vertexShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vertex"), 0);
470 	m_fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("fragment"), 0);
471 
472 	// Create pipelines
473 	{
474 		const VkVertexInputBindingDescription		vertexInputBindingDescription		=
475 		{
476 			0u,								// deUint32					binding;
477 			sizeof(Vertex),					// deUint32					strideInBytes;
478 			VK_VERTEX_INPUT_RATE_VERTEX		// VkVertexInputStepRate	inputRate;
479 		};
480 
481 		std::vector<VkVertexInputAttributeDescription> vertexInputAttributeDescription	=
482 		{
483 			{
484 				0u,								// deUint32		location;
485 				0u,								// deUint32		binding;
486 				VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat		format;
487 				0u								// deUint32		offset;
488 			},
489 			{
490 				1u,								// deUint32		location;
491 				0u,								// deUint32		binding;
492 				VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat		format;
493 				DE_OFFSET_OF(Vertex, uv)		// deUint32		offset;
494 			}
495 		};
496 
497 		const VkPipelineVertexInputStateCreateInfo	vertexInputStateParams				=
498 		{
499 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
500 			DE_NULL,														// const void*								pNext;
501 			0u,																// VkPipelineVertexInputStateCreateFlags	flags;
502 			1u,																// deUint32									vertexBindingDescriptionCount;
503 			&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
504 			static_cast<deUint32>(vertexInputAttributeDescription.size()),	// deUint32									vertexAttributeDescriptionCount;
505 			vertexInputAttributeDescription.data()							// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
506 		};
507 
508 		const std::vector<VkViewport>				viewports							(1, makeViewport(m_renderSize));
509 		const std::vector<VkRect2D>					scissors							(1, makeRect2D(m_renderSize));
510 
511 		{
512 			m_graphicsPipeline	= makeGraphicsPipeline(vk,									// const DeviceInterface&						vk
513 													  vkDevice,								// const VkDevice								device
514 													  *m_pipelineLayout,					// const VkPipelineLayout						pipelineLayout
515 													  *m_vertexShaderModule,				// const VkShaderModule							vertexShaderModule
516 													  DE_NULL,								// const VkShaderModule							tessellationControlModule
517 													  DE_NULL,								// const VkShaderModule							tessellationEvalModule
518 													  DE_NULL,								// const VkShaderModule							geometryShaderModule
519 													  *m_fragmentShaderModule,				// const VkShaderModule							fragmentShaderModule
520 													  *m_renderPass,						// const VkRenderPass							renderPass
521 													  viewports,							// const std::vector<VkViewport>&				viewports
522 													  scissors,								// const std::vector<VkRect2D>&					scissors
523 													  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology					topology
524 													  0u,									// const deUint32								subpass
525 													  0u,									// const deUint32								patchControlPoints
526 													  &vertexInputStateParams);				// const VkPipelineVertexInputStateCreateInfo*	vertexInputStateCreateInfo
527 		}
528 	}
529 
530 	// Create vertex buffer
531 	{
532 		const VkBufferCreateInfo vertexBufferParams =
533 		{
534 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,					// VkStructureType		sType;
535 			DE_NULL,												// const void*			pNext;
536 			0u,														// VkBufferCreateFlags	flags;
537 			(VkDeviceSize)(sizeof(Vertex) * m_vertices.size()),		// VkDeviceSize			size;
538 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,						// VkBufferUsageFlags	usage;
539 			VK_SHARING_MODE_EXCLUSIVE,								// VkSharingMode		sharingMode;
540 			1u,														// deUint32				queueFamilyIndexCount;
541 			&queueFamilyIndex										// const deUint32*		pQueueFamilyIndices;
542 		};
543 
544 		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
545 		m_vertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
546 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
547 
548 		// Upload vertex data
549 		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex));
550 		flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
551 	}
552 
553 	// Create command pool
554 	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
555 
556 	// Create command buffer
557 	if (testParams.renderPassType == RENDERPASS_TYPE_LEGACY)
558 		createCommandBuffer<RenderpassSubpass1>(vk, vkDevice);
559 	else
560 		createCommandBuffer<RenderpassSubpass2>(vk, vkDevice);
561 }
562 
~InputAttachmentSparseFillingTestInstance(void)563 InputAttachmentSparseFillingTestInstance::~InputAttachmentSparseFillingTestInstance (void)
564 {
565 }
566 
567 template<typename RenderpassSubpass>
createCommandBuffer(const DeviceInterface & vk,VkDevice vkDevice)568 void InputAttachmentSparseFillingTestInstance::createCommandBuffer (const DeviceInterface&	vk,
569 																	VkDevice				vkDevice)
570 {
571 	m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
572 
573 	beginCommandBuffer(vk, *m_cmdBuffer, 0u);
574 
575 	// clear output image (rg16ui) to (0,0), set image layout to VK_IMAGE_LAYOUT_GENERAL
576 	VkImageSubresourceRange		range				= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
577 	{
578 		const VkImageMemoryBarrier	outputImageInitBarrier =
579 		{
580 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,					// VkStructureType			sType;
581 			DE_NULL,												// const void*				pNext;
582 			0u,														// VkAccessFlags			srcAccessMask;
583 			VK_ACCESS_TRANSFER_WRITE_BIT,							// VkAccessFlags			dstAcessMask;
584 			VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout			oldLayout;
585 			VK_IMAGE_LAYOUT_GENERAL,								// VkImageLayout			newLayout;
586 			VK_QUEUE_FAMILY_IGNORED,								// deUint32					srcQueueFamilyIndex;
587 			VK_QUEUE_FAMILY_IGNORED,								// deUint32					destQueueFamilyIndex;
588 			**m_outputImage,										// VkImage					image;
589 			range													// VkImageSubresourceRange	subresourceRange;
590 		};
591 		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &outputImageInitBarrier);
592 		VkClearValue				clearColor = makeClearValueColorU32(0, 0, 0, 0);
593 		vk.cmdClearColorImage(*m_cmdBuffer, **m_outputImage, VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range);
594 		VkMemoryBarrier					memBarrier =
595 		{
596 			VK_STRUCTURE_TYPE_MEMORY_BARRIER,						// sType
597 			DE_NULL,												// pNext
598 			VK_ACCESS_TRANSFER_WRITE_BIT,							// srcAccessMask
599 			VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT	// dstAccessMask
600 		};
601 		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
602 			0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
603 	}
604 	// clear all input attachments (rgba8) to (1,1,1,1), set image layout to VK_IMAGE_LAYOUT_GENERAL
605 	for (auto& inputImage : m_inputImages)
606 	{
607 		const VkImageMemoryBarrier	inputImageInitBarrier =
608 		{
609 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
610 			DE_NULL,											// const void*				pNext;
611 			0u,													// VkAccessFlags			srcAccessMask;
612 			VK_ACCESS_MEMORY_WRITE_BIT,							// VkAccessFlags			dstAcessMask;
613 			VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			oldLayout;
614 			VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout			newLayout;
615 			VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
616 			VK_QUEUE_FAMILY_IGNORED,							// deUint32					destQueueFamilyIndex;
617 			**inputImage,										// VkImage					image;
618 			range												// VkImageSubresourceRange	subresourceRange;
619 		};
620 		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &inputImageInitBarrier);
621 		VkClearValue				clearColor = makeClearValueColorF32(1.0f, 1.0f, 1.0f, 1.0f);
622 
623 		vk.cmdClearColorImage(*m_cmdBuffer, **inputImage, VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range);
624 
625 		VkMemoryBarrier					memBarrier =
626 		{
627 			VK_STRUCTURE_TYPE_MEMORY_BARRIER,					// sType
628 			DE_NULL,											// pNext
629 			VK_ACCESS_TRANSFER_WRITE_BIT,						// srcAccessMask
630 			VK_ACCESS_INPUT_ATTACHMENT_READ_BIT					// dstAccessMask
631 		};
632 		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
633 			0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
634 	}
635 
636 	// Render pass does not use clear values - input images were prepared beforehand
637 	const VkRenderPassBeginInfo renderPassBeginInfo =
638 	{
639 		VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,				// VkStructureType		sType;
640 		DE_NULL,												// const void*			pNext;
641 		*m_renderPass,											// VkRenderPass			renderPass;
642 		*m_framebuffer,											// VkFramebuffer		framebuffer;
643 		makeRect2D(m_renderSize),								// VkRect2D				renderArea;
644 		0,														// uint32_t				clearValueCount;
645 		DE_NULL													// const VkClearValue*	pClearValues;
646 	};
647 	const typename RenderpassSubpass::SubpassBeginInfo	subpassBeginInfo(DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
648 	RenderpassSubpass::cmdBeginRenderPass(vk, *m_cmdBuffer, &renderPassBeginInfo, &subpassBeginInfo);
649 
650 	const VkDeviceSize			vertexBufferOffset = 0;
651 	vk.cmdBindPipeline			(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
652 	vk.cmdBindDescriptorSets	(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
653 	vk.cmdBindVertexBuffers		(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
654 	vk.cmdDraw					(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
655 
656 	const typename RenderpassSubpass::SubpassEndInfo	subpassEndInfo(DE_NULL);
657 	RenderpassSubpass::cmdEndRenderPass(vk, *m_cmdBuffer, &subpassEndInfo);
658 
659 	copyImageToBuffer(vk, *m_cmdBuffer, **m_outputImage, **m_outputBuffer, tcu::IVec2(m_renderSize.x(), m_renderSize.y()), VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
660 
661 	endCommandBuffer(vk, *m_cmdBuffer);
662 }
663 
664 template<typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep, typename RenderPassCreateInfo>
createRenderPass(const DeviceInterface & vk,VkDevice vkDevice)665 Move<VkRenderPass> InputAttachmentSparseFillingTestInstance::createRenderPass (const DeviceInterface&	vk,
666 																			   VkDevice					vkDevice)
667 {
668 	const VkImageAspectFlags	aspectMask						= m_testParams.renderPassType == RENDERPASS_TYPE_LEGACY ? 0 : VK_IMAGE_ASPECT_COLOR_BIT;
669 	std::vector<AttachmentDesc>	attachmentDescriptions;
670 	std::vector<AttachmentRef>	attachmentRefs;
671 
672 	std::vector<deUint32>		attachmentIndices;
673 	std::vector<deUint32>		descriptorBindings;
674 	generateInputAttachmentParams(m_testParams.activeInputAttachmentCount, 2u * m_testParams.activeInputAttachmentCount, attachmentIndices, descriptorBindings);
675 
676 	for (deUint32 i = 0; i < m_testParams.activeInputAttachmentCount; ++i)
677 	{
678 		attachmentDescriptions.push_back(
679 			AttachmentDesc(
680 				DE_NULL,									// const void*						pNext
681 				(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags		flags
682 				VK_FORMAT_R8G8B8A8_UNORM,					// VkFormat							format
683 				VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits			samples
684 				VK_ATTACHMENT_LOAD_OP_LOAD,					// VkAttachmentLoadOp				loadOp
685 				VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp
686 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp				stencilLoadOp
687 				VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp				stencilStoreOp
688 				VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout					initialLayout
689 				VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL	// VkImageLayout					finalLayout
690 			)
691 		);
692 	}
693 	for (std::size_t i = 0; i < attachmentIndices.size(); ++i)
694 		attachmentRefs.push_back(
695 			AttachmentRef(
696 				DE_NULL,									// const void*			pNext
697 				attachmentIndices[i],						// deUint32				attachment
698 				VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,	// VkImageLayout		layout
699 				aspectMask									// VkImageAspectFlags	aspectMask
700 			)
701 		);
702 
703 	std::vector<SubpassDesc>		subpassDescriptions			=
704 	{
705 		SubpassDesc (
706 			DE_NULL,
707 			(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags		flags
708 			VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint
709 			0u,													// deUint32							viewMask
710 			static_cast<deUint32>(attachmentRefs.size()),		// deUint32							inputAttachmentCount
711 			attachmentRefs.data(),								// const VkAttachmentReference*		pInputAttachments
712 			0u,													// deUint32							colorAttachmentCount
713 			DE_NULL,											// const VkAttachmentReference*		pColorAttachments
714 			DE_NULL,											// const VkAttachmentReference*		pResolveAttachments
715 			DE_NULL,											// const VkAttachmentReference*		pDepthStencilAttachment
716 			0u,													// deUint32							preserveAttachmentCount
717 			DE_NULL												// const deUint32*					pPreserveAttachments
718 		),
719 	};
720 	std::vector<SubpassDep>		subpassDependencies =
721 	{
722 		SubpassDep (
723 			DE_NULL,
724 			0u,										// deUint32				srcPass
725 			VK_SUBPASS_EXTERNAL,					// deUint32				dstPass
726 			VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,	// VkPipelineStageFlags	srcStageMask
727 			VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT,	// VkPipelineStageFlags	dstStageMask
728 			VK_ACCESS_SHADER_WRITE_BIT,				// VkAccessFlags		srcAccessMask
729 			VK_ACCESS_INDIRECT_COMMAND_READ_BIT,	// VkAccessFlags		dstAccessMask
730 			0,										// VkDependencyFlags	flags
731 			0										// deInt32				viewOffset
732 		),
733 	};
734 
735 	const RenderPassCreateInfo	renderPassInfo					(
736 		DE_NULL,												// const void*						pNext
737 		(VkRenderPassCreateFlags)0,								// VkRenderPassCreateFlags			flags
738 		static_cast<deUint32>(attachmentDescriptions.size()),	// deUint32							attachmentCount
739 		attachmentDescriptions.data(),							// const VkAttachmentDescription*	pAttachments
740 		static_cast<deUint32>(subpassDescriptions.size()),		// deUint32							subpassCount
741 		subpassDescriptions.data(),								// const VkSubpassDescription*		pSubpasses
742 		static_cast<deUint32>(subpassDependencies.size()),		// deUint32							dependencyCount
743 		subpassDependencies.data(),								// const VkSubpassDependency*		pDependencies
744 		0u,														// deUint32							correlatedViewMaskCount
745 		DE_NULL													// const deUint32*					pCorrelatedViewMasks
746 	);
747 
748 	return renderPassInfo.createRenderPass(vk, vkDevice);
749 }
750 
iterate(void)751 tcu::TestStatus InputAttachmentSparseFillingTestInstance::iterate (void)
752 {
753 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
754 	const VkDevice				vkDevice	= m_context.getDevice();
755 	const VkQueue				queue		= m_context.getUniversalQueue();
756 
757 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
758 
759 	return verifyImage();
760 }
761 
verifyImage(void)762 tcu::TestStatus InputAttachmentSparseFillingTestInstance::verifyImage (void)
763 {
764 	const DeviceInterface&				vk						= m_context.getDeviceInterface();
765 	const VkDevice						vkDevice				= m_context.getDevice();
766 
767 	invalidateAlloc(vk, vkDevice, *m_outputBufferMemory);
768 	const tcu::ConstPixelBufferAccess resultAccess(mapVkFormat(VK_FORMAT_R32G32_UINT), m_renderSize.x(), m_renderSize.y(), 1u, m_outputBufferMemory->getHostPtr());
769 
770 	// Log result image
771 	m_context.getTestContext().getLog() << tcu::TestLog::ImageSet("Result", "Result images")
772 		<< tcu::TestLog::Image("Rendered", "Rendered image", resultAccess)
773 		<< tcu::TestLog::EndImageSet;
774 
775 	// Check the unused image data hasn't changed.
776 	for (int y = 0; y < resultAccess.getHeight(); y++)
777 		for (int x = 0; x < resultAccess.getWidth(); x++)
778 		{
779 			tcu::UVec4 color = resultAccess.getPixelUint(x, y);
780 			if( color.x() != m_testParams.activeInputAttachmentCount)
781 				return tcu::TestStatus::fail("Wrong attachment count");
782 			if( color.y() != m_testParams.activeInputAttachmentCount )
783 				return tcu::TestStatus::fail("Wrong active attachment count");
784 		}
785 
786 	return tcu::TestStatus::pass("Pass");
787 }
788 
789 } // anonymous
790 
createRenderPassUnusedAttachmentSparseFillingTests(tcu::TestContext & testCtx,const RenderPassType renderPassType)791 tcu::TestCaseGroup* createRenderPassUnusedAttachmentSparseFillingTests (tcu::TestContext& testCtx, const RenderPassType renderPassType)
792 {
793 	de::MovePtr<tcu::TestCaseGroup>		unusedAttTests		(new tcu::TestCaseGroup(testCtx, "attachment_sparse_filling", "Unused attachment tests"));
794 
795 	const std::vector<deUint32> activeInputAttachmentCount
796 	{
797 		1u,
798 		3u,
799 		7u,
800 		15u,
801 		31u,
802 		63u,
803 		127u
804 	};
805 
806 	for (std::size_t attachmentNdx = 0; attachmentNdx < activeInputAttachmentCount.size(); ++attachmentNdx)
807 	{
808 		TestParams testParams{ renderPassType, activeInputAttachmentCount[attachmentNdx] };
809 		unusedAttTests->addChild(new InputAttachmentSparseFillingTest(testCtx, std::string("input_attachment_") + de::toString(activeInputAttachmentCount[attachmentNdx]), "", testParams));
810 	}
811 
812 	return unusedAttTests.release();
813 }
814 
815 } // renderpass
816 
817 } // vkt
818