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