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