• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2022 The Khronos Group Inc.
6  * Copyright (c) 2022 Google Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file vktPipelineMultisampleResolveRenderAreaTests.hpp
22  * \brief Multisample resolve tests where a render area is less than an
23  *        attachment size.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktPipelineMultisampleResolveRenderAreaTests.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vktTestGroupUtil.hpp"
29 
30 #include "vkCmdUtil.hpp"
31 #include "vkImageUtil.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkObjUtil.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 
37 #include "tcuImageCompare.hpp"
38 #include "tcuTestLog.hpp"
39 
40 namespace vkt
41 {
42 namespace pipeline
43 {
44 using namespace vk;
45 using de::UniquePtr;
46 
47 namespace
48 {
49 
50 enum class TestShape
51 {
52 	SHAPE_RECTANGLE,
53 	SHAPE_DIAMOND,
54 	SHAPE_PARALLELOGRAM
55 };
56 
57 class MultisampleRenderAreaTestInstance : public TestInstance
58 {
59 public:
MultisampleRenderAreaTestInstance(Context & context,const PipelineConstructionType pipelineConstructionType,const deUint32 sampleCount,const tcu::IVec2 framebufferSize,const TestShape testShape,const VkFormat colorFormat)60 					MultisampleRenderAreaTestInstance	(Context&							context,
61 														 const PipelineConstructionType		pipelineConstructionType,
62 														 const deUint32						sampleCount,
63 														 const tcu::IVec2					framebufferSize,
64 														 const TestShape					testShape,
65 														 const VkFormat						colorFormat)
66 														: TestInstance					(context)
67 														, m_pipelineConstructionType	(pipelineConstructionType)
68 														, m_sampleCount					(sampleCount)
69 														, m_framebufferSize				(framebufferSize)
70 														, m_testShape					(testShape)
71 														, m_colorFormat					(colorFormat)
72 														{}
73 
74 	tcu::TestStatus	iterate								(void);
75 
76 private:
77 	VkImageCreateInfo	makeImageCreateInfo		(const tcu::IVec2& imageSize, const deUint32 sampleCount);
78 
79 	Move<VkRenderPass>	makeRenderPass			(const DeviceInterface&		vk,
80 												 const VkDevice				device,
81 												 const VkFormat				colorFormat,
82 												 const VkImageLayout		initialLayout);
83 
84 	void				preparePipelineWrapper	(GraphicsPipelineWrapper&	gpw,
85 												 const VkPipelineLayout		pipelineLayout,
86 												 const VkRenderPass			renderPass,
87 												 const VkShaderModule		vertexModule,
88 												 const VkShaderModule		fragmentModule,
89 												 const tcu::IVec2&			framebufferSize);
90 
91 	const PipelineConstructionType		m_pipelineConstructionType;
92 	const deUint32						m_sampleCount;
93 	const tcu::IVec2					m_framebufferSize;
94 	const TestShape						m_testShape;
95 	const VkFormat						m_colorFormat;
96 };
97 
makeImageCreateInfo(const tcu::IVec2 & imageSize,const deUint32 sampleCount)98 VkImageCreateInfo MultisampleRenderAreaTestInstance::makeImageCreateInfo(const tcu::IVec2& imageSize, const deUint32 sampleCount)
99 {
100 	const VkImageCreateInfo imageParams =
101 	{
102 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,												// VkStructureType			sType;
103 		DE_NULL,																			// const void*				pNext;
104 		(VkImageCreateFlags)0,																// VkImageCreateFlags		flags;
105 		VK_IMAGE_TYPE_2D,																	// VkImageType				imageType;
106 		m_colorFormat,																		// VkFormat					format;
107 		makeExtent3D(imageSize.x(), imageSize.y(), 1),										// VkExtent3D				extent;
108 		1u,																					// deUint32					mipLevels;
109 		1u,																					// deUint32					arrayLayers;
110 		sampleCount < 2u ? VK_SAMPLE_COUNT_1_BIT : (VkSampleCountFlagBits)m_sampleCount,	// VkSampleCountFlagBits	samples;
111 		VK_IMAGE_TILING_OPTIMAL,															// VkImageTiling			tiling;
112 		VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,				// VkImageUsageFlags		usage;
113 		VK_SHARING_MODE_EXCLUSIVE,															// VkSharingMode			sharingMode;
114 		0u,																					// deUint32					queueFamilyIndexCount;
115 		DE_NULL,																			// const deUint32*			pQueueFamilyIndices;
116 		VK_IMAGE_LAYOUT_UNDEFINED,															// VkImageLayout			initialLayout;
117 	};
118 
119 	return imageParams;
120 }
121 
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const VkImageLayout initialLayout)122 Move<VkRenderPass> MultisampleRenderAreaTestInstance::makeRenderPass (const DeviceInterface&	vk,
123 																	  const VkDevice			device,
124 																	  const VkFormat			colorFormat,
125 																	  const VkImageLayout		initialLayout)
126 {
127 	const VkAttachmentDescription			colorAttachmentDescription		=
128 	{
129 		(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags	flags;
130 		colorFormat,								// VkFormat						format;
131 		(VkSampleCountFlagBits)m_sampleCount,		// VkSampleCountFlagBits		samples;
132 		VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp			loadOp;
133 		VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp			storeOp;
134 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp			stencilLoadOp;
135 		VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp			stencilStoreOp;
136 		initialLayout,								// VkImageLayout				initialLayout;
137 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout				finalLayout;
138 	};
139 
140 	const VkAttachmentDescription			resolveAttachmentDescription	=
141 	{
142 		(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags	flags;
143 		colorFormat,								// VkFormat						format;
144 		VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits		samples;
145 		VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp			loadOp;
146 		VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp			storeOp;
147 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp			stencilLoadOp;
148 		VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp			stencilStoreOp;
149 		initialLayout,								// VkImageLayout				initialLayout;
150 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout				finalLayout;
151 	};
152 
153 	std::vector<VkAttachmentDescription>	attachmentDescriptions;
154 
155 	attachmentDescriptions.push_back(colorAttachmentDescription);
156 	attachmentDescriptions.push_back(resolveAttachmentDescription);
157 
158 	const VkAttachmentReference				colorAttachmentRef				=
159 	{
160 		0u,											// uint32_t			attachment;
161 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout	layout;
162 	};
163 
164 	const VkAttachmentReference				resolveAttachmentRef			=
165 	{
166 		1u,											// uint32_t			attachment;
167 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout	layout;
168 	};
169 
170 	const VkSubpassDescription				subpassDescription				=
171 	{
172 		(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags		flags;
173 		VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint				pipelineBindPoint;
174 		0u,									// uint32_t							inputAttachmentCount;
175 		DE_NULL,							// const VkAttachmentReference*		pInputAttachments;
176 		1u,									// uint32_t							colorAttachmentCount;
177 		&colorAttachmentRef,				// const VkAttachmentReference*		pColorAttachments;
178 		&resolveAttachmentRef,				// const VkAttachmentReference*		pResolveAttachments;
179 		DE_NULL,							// const VkAttachmentReference*		pDepthStencilAttachment;
180 		0u,									// uint32_t							preserveAttachmentCount;
181 		DE_NULL								// const uint32_t*					pPreserveAttachments;
182 	};
183 
184 	const VkRenderPassCreateInfo			renderPassInfo					=
185 	{
186 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType					sType;
187 		DE_NULL,									// const void*						pNext;
188 		(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags;
189 		(deUint32)attachmentDescriptions.size(),	// uint32_t							attachmentCount;
190 		attachmentDescriptions.data(),				// const VkAttachmentDescription*	pAttachments;
191 		1u,											// uint32_t							subpassCount;
192 		&subpassDescription,						// const VkSubpassDescription*		pSubpasses;
193 		0u,											// uint32_t							dependencyCount;
194 		DE_NULL,									// const VkSubpassDependency*		pDependencies;
195 	};
196 
197 	return createRenderPass(vk, device, &renderPassInfo);
198 }
199 
preparePipelineWrapper(GraphicsPipelineWrapper & gpw,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const tcu::IVec2 & framebufferSize)200 void MultisampleRenderAreaTestInstance::preparePipelineWrapper (GraphicsPipelineWrapper&	gpw,
201 																const VkPipelineLayout		pipelineLayout,
202 																const VkRenderPass			renderPass,
203 																const VkShaderModule		vertexModule,
204 																const VkShaderModule		fragmentModule,
205 																const tcu::IVec2&			framebufferSize)
206 {
207 	const std::vector<VkViewport>	viewports		{ makeViewport(framebufferSize) };
208 	const std::vector<VkRect2D>		scissors		{ makeRect2D(framebufferSize) };
209 	VkSampleMask					sampleMask		= 0xffff;
210 
211 	const VkPipelineMultisampleStateCreateInfo	multisampleStateCreateInfo
212 	{
213 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType
214 		DE_NULL,													// const void*								pNext
215 		0u,															// VkPipelineMultisampleStateCreateFlags	flags
216 		(VkSampleCountFlagBits)m_sampleCount,						// VkSampleCountFlagBits					rasterizationSamples
217 		DE_FALSE,													// VkBool32									sampleShadingEnable
218 		0.0f,														// float									minSampleShading
219 		&sampleMask,												// const VkSampleMask*						pSampleMask
220 		DE_FALSE,													// VkBool32									alphaToCoverageEnable
221 		DE_FALSE,													// VkBool32									alphaToOneEnable
222 	};
223 
224 	gpw.setDefaultDepthStencilState()
225 	   .setDefaultColorBlendState()
226 	   .setDefaultRasterizationState()
227 	   .setupVertexInputState()
228 	   .setupPreRasterizationShaderState(viewports,
229 			scissors,
230 			pipelineLayout,
231 			renderPass,
232 			0u,
233 			vertexModule)
234 	   .setupFragmentShaderState(pipelineLayout,
235 			renderPass,
236 			0u,
237 			fragmentModule,
238 			DE_NULL,
239 			&multisampleStateCreateInfo)
240 	   .setupFragmentOutputState(renderPass, 0u, DE_NULL, &multisampleStateCreateInfo)
241 	   .setMonolithicPipelineLayout(pipelineLayout)
242 	   .buildPipeline();
243 }
244 
iterate(void)245 tcu::TestStatus	MultisampleRenderAreaTestInstance::iterate (void)
246 {
247 	const DeviceInterface&			vk						= m_context.getDeviceInterface();
248 	const VkDevice					device					= m_context.getDevice();
249 	Allocator&						allocator				= m_context.getDefaultAllocator();
250 	const VkQueue					queue					= m_context.getUniversalQueue();
251 	const deUint32					queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
252 	const VkImageSubresourceRange	colorSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
253 
254 	const Unique<VkShaderModule>	vertexModule			(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
255 	const Unique<VkShaderModule>	fragmentModule			(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
256 
257 	const Unique<VkImage>			colorImage				(makeImage(vk, device, makeImageCreateInfo(m_framebufferSize, m_sampleCount)));
258 	const UniquePtr<Allocation>		colorImageAlloc			(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
259 	const Unique<VkImageView>		colorImageView			(makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, colorSubresourceRange));
260 
261 	const Unique<VkImage>			resolveColorImage		(makeImage(vk, device, makeImageCreateInfo(m_framebufferSize, 1u)));
262 	const UniquePtr<Allocation>		resolveColorImageAlloc	(bindImage(vk, device, allocator, *resolveColorImage, MemoryRequirement::Any));
263 	const Unique<VkImageView>		resolveColorImageView	(makeImageView(vk, device, *resolveColorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, colorSubresourceRange));
264 
265 	const VkImageView				attachmentImages[]		= { *colorImageView, *resolveColorImageView };
266 	const deUint32					numUsedAttachmentImages	= DE_LENGTH_OF_ARRAY(attachmentImages);
267 
268 	const VkDeviceSize				colorBufferSizeBytes	= tcu::getPixelSize(mapVkFormat(m_colorFormat)) * m_framebufferSize.x() * m_framebufferSize.y();
269 	const Unique<VkBuffer>			colorBufferResults		(makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
270 	const UniquePtr<Allocation>		colorBufferAlloc		(bindBuffer(vk, device, allocator, *colorBufferResults, MemoryRequirement::HostVisible));
271 
272 	const Unique<VkRenderPass>		renderPassOne			(makeRenderPass(vk, device, m_colorFormat, VK_IMAGE_LAYOUT_UNDEFINED));
273 	const Unique<VkRenderPass>		renderPassTwo			(makeRenderPass(vk, device, m_colorFormat, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
274 	const Unique<VkFramebuffer>		framebuffer				(makeFramebuffer(vk, device, *renderPassOne, numUsedAttachmentImages, attachmentImages, m_framebufferSize.x(), m_framebufferSize.y()));
275 
276 	const Unique<VkPipelineLayout>	pipelineLayout			(makePipelineLayout(vk, device, DE_NULL));
277 	GraphicsPipelineWrapper			graphicsPipeline		{vk, device, m_pipelineConstructionType};
278 
279 	const Unique<VkCommandPool>		cmdPool					(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
280 	const Unique<VkCommandBuffer>	commandBuffer			(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
281 
282 	// Main vertex buffer
283 	const deUint32					numVertices				= 6;
284 	const VkDeviceSize				vertexBufferSizeBytes	= 256;
285 	const Unique<VkBuffer>			vertexBuffer			(makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
286 	const UniquePtr<Allocation>		vertexBufferAlloc		(bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
287 
288 	preparePipelineWrapper(graphicsPipeline, *pipelineLayout, *renderPassOne, *vertexModule, *fragmentModule, m_framebufferSize);
289 
290 	{
291 		tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
292 
293 		// The shapes should fit just and just inside the renderArea.
294 		if (m_testShape == TestShape::SHAPE_RECTANGLE)
295 		{
296 			float size = 0.5f;
297 
298 			pVertices[0] = tcu::Vec4(size, -size, 0.0f, 1.0f);
299 			pVertices[1] = tcu::Vec4(-size, -size, 0.0f, 1.0f);
300 			pVertices[2] = tcu::Vec4(-size, size, 0.0f, 1.0f);
301 
302 			pVertices[3] = tcu::Vec4(-size, size, 0.0f, 1.0f);
303 			pVertices[4] = tcu::Vec4(size, size, 0.0f, 1.0f);
304 			pVertices[5] = tcu::Vec4(size, -size, 0.0f, 1.0f);
305 		}
306 
307 		if (m_testShape == TestShape::SHAPE_DIAMOND)
308 		{
309 			float size		= 0.5f;
310 
311 			pVertices[0]	= tcu::Vec4( size,  0.0f, 0.0f, 1.0f);
312 			pVertices[1]	= tcu::Vec4(-0.0f, -size, 0.0f, 1.0f);
313 			pVertices[2]	= tcu::Vec4(-size,  0.0f, 0.0f, 1.0f);
314 
315 			pVertices[3]	= tcu::Vec4( size,  0.0f, 0.0f, 1.0f);
316 			pVertices[4]	= tcu::Vec4(-size,  0.0f, 0.0f, 1.0f);
317 			pVertices[5]	= tcu::Vec4(-0.0f,  size, 0.0f, 1.0f);
318 		}
319 
320 		if (m_testShape == TestShape::SHAPE_PARALLELOGRAM)
321 		{
322 			float size = 0.3125f;
323 
324 			pVertices[0] = tcu::Vec4(size, -size, 0.0f, 1.0f);
325 			pVertices[1] = tcu::Vec4(-0.5f, -size, 0.0f, 1.0f);
326 			pVertices[2] = tcu::Vec4(-size, size, 0.0f, 1.0f);
327 
328 			pVertices[3] = tcu::Vec4(-size, size, 0.0f, 1.0f);
329 			pVertices[4] = tcu::Vec4(0.5f, size, 0.0f, 1.0f);
330 			pVertices[5] = tcu::Vec4(size, -size, 0.0f, 1.0f);
331 		}
332 
333 		flushAlloc(vk, device, *vertexBufferAlloc);
334 	}
335 
336 	const VkDeviceSize				vertexBufferOffset		= 0ull;
337 
338 	const VkRect2D					testRenderArea			=
339 	{
340 		makeOffset2D(m_framebufferSize.x() / 4u, m_framebufferSize.x() / 4u),
341 		makeExtent2D(m_framebufferSize.x() / 2u, m_framebufferSize.y() / 2u),
342 	};
343 
344 	const std::vector<VkClearValue>	clearValuesFullArea		= { makeClearValueColor(tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)), makeClearValueColor(tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)) };
345 	const std::vector<VkClearValue>	clearValuesTestArea		= { makeClearValueColor(tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f)), makeClearValueColor(tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f)) };
346 
347 	beginCommandBuffer(vk, *commandBuffer);
348 
349 	const VkRect2D					fullRenderArea			=
350 	{
351 		makeOffset2D(0u, 0u),
352 		makeExtent2D(m_framebufferSize.x(), m_framebufferSize.y()),
353 	};
354 
355 	// Clear whole render area with red color.
356 	beginRenderPass(vk, *commandBuffer, *renderPassOne, *framebuffer, fullRenderArea, static_cast<deUint32>(clearValuesFullArea.size()), clearValuesFullArea.data());
357 	endRenderPass(vk, *commandBuffer);
358 
359 	// Draw shape when render area size is halved.
360 	beginRenderPass(vk, *commandBuffer, *renderPassTwo, *framebuffer, testRenderArea, static_cast<deUint32>(clearValuesTestArea.size()), clearValuesTestArea.data());
361 	vk.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
362 	vk.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline.getPipeline());
363 	vk.cmdDraw(*commandBuffer, numVertices, 1u, 0u, 0u);
364 	endRenderPass(vk, *commandBuffer);
365 
366 	copyImageToBuffer(vk, *commandBuffer, *resolveColorImage, *colorBufferResults, m_framebufferSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
367 
368 	endCommandBuffer(vk, *commandBuffer);
369 	submitCommandsAndWait(vk, device, queue, *commandBuffer);
370 
371 	// Verify color output
372 	{
373 		invalidateAlloc(vk, device, *colorBufferAlloc);
374 
375 		tcu::TestLog&						log					= m_context.getTestContext().getLog();
376 		const Unique<VkBuffer>				testBufferResults	(makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
377 		tcu::ConstPixelBufferAccess			imageAccess			(mapVkFormat(m_colorFormat), m_framebufferSize.x(), m_framebufferSize.y(), 1, colorBufferAlloc->getHostPtr());
378 
379 		// Color check for rendered shape. Shape color is yellow.
380 		if (imageAccess.getPixel(m_framebufferSize.x() / 2, m_framebufferSize.y() / 2) != tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f))
381 		{
382 			log << tcu::TestLog::Image("color0", "Rendered image", imageAccess);
383 			return tcu::TestStatus::fail("Pixel check failed: shape color");
384 		}
385 
386 		// Color check for the second render area. Clear color should be green.
387 		if (m_testShape != TestShape::SHAPE_RECTANGLE)	// In this case the shape has covered the whole render area.
388 		{
389 			if (imageAccess.getPixel(m_framebufferSize.x() / 4 + 1, m_framebufferSize.y() / 4 + 1) != tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f))
390 			{
391 				log << tcu::TestLog::Image("color0", "Rendered image", imageAccess);
392 				return tcu::TestStatus::fail("Pixel check failed inside the render area");
393 			}
394 		}
395 
396 		// Color check for possible overflowed multisample pixels outside of the second render area.
397 		// Clear color after the first beginRenderPass should be red.
398 		const int							minValue			= m_framebufferSize.y() / 4 - 1;
399 		const int							maxValue			= m_framebufferSize.y() - m_framebufferSize.y() / 4;
400 
401 		for (int y = 0; y < m_framebufferSize.y(); y++)
402 		{
403 			for (int x = 0; x < m_framebufferSize.x(); x++)
404 			{
405 				if (!(x > minValue && y > minValue && x < maxValue && y < maxValue))
406 				{
407 					if (imageAccess.getPixel(x, y) != tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f))
408 					{
409 						log << tcu::TestLog::Message << "Incorrect color value " << imageAccess.getPixel(x, y) << " at location (" << x << ", " << y << ")" << tcu::TestLog::EndMessage;
410 						log << tcu::TestLog::Image("color0", "Rendered image", imageAccess);
411 						return tcu::TestStatus::fail("Pixel check failed outside the render area");
412 					}
413 				}
414 			}
415 		}
416 	}
417 
418 	return tcu::TestStatus::pass("Success");
419 }
420 
421 class MultisampleRenderAreaTest : public TestCase
422 {
423 public:
MultisampleRenderAreaTest(tcu::TestContext & testCtx,const std::string name,const PipelineConstructionType pipelineConstructionType,const deUint32 sampleCount,const tcu::IVec2 framebufferSize,const TestShape testShape,const VkFormat colorFormat=VK_FORMAT_R8G8B8A8_UNORM)424 						MultisampleRenderAreaTest	(tcu::TestContext&					testCtx,
425 													 const std::string					name,
426 													 const PipelineConstructionType		pipelineConstructionType,
427 													 const deUint32						sampleCount,
428 													 const tcu::IVec2					framebufferSize,
429 													 const TestShape					testShape,
430 													 const VkFormat						colorFormat	= VK_FORMAT_R8G8B8A8_UNORM)
431 													: TestCase(testCtx,	name, "")
432 													, m_pipelineConstructionType	(pipelineConstructionType)
433 													, m_sampleCount					(sampleCount)
434 													, m_framebufferSize				(framebufferSize)
435 													, m_testShape					(testShape)
436 													, m_colorFormat					(colorFormat)
437 													{}
438 
439 	void				initPrograms				(SourceCollections&	programCollection) const;
440 	TestInstance*		createInstance				(Context&			context) const;
441 	virtual void		checkSupport				(Context&			context) const;
442 
443 private:
444 
445 	const PipelineConstructionType	m_pipelineConstructionType;
446 	const deUint32					m_sampleCount;
447 	const tcu::IVec2				m_framebufferSize;
448 	const TestShape					m_testShape;
449 	const VkFormat					m_colorFormat;
450 };
451 
initPrograms(SourceCollections & programCollection) const452 void MultisampleRenderAreaTest::initPrograms(SourceCollections& programCollection) const
453 {
454 	// Vertex shader
455 	{
456 		std::ostringstream src;
457 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
458 			<< "\n"
459 			<< "layout(location = 0) in vec4 position;\n"
460 			<< "\n"
461 			<< "void main (void)\n"
462 			<< "{\n"
463 			<< "	gl_Position = position;\n"
464 			<< "}\n";
465 
466 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
467 	}
468 
469 	// Fragment shader
470 	{
471 		std::ostringstream frg;
472 		frg << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
473 			<< "\n"
474 			<< "layout(location = 0) out vec4 fragColor;\n"
475 			<< "\n"
476 			<< "void main (void)\n"
477 			<< "{\n"
478 			<< "	fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
479 			<< "}\n";
480 
481 		programCollection.glslSources.add("frag") << glu::FragmentSource(frg.str());
482 	}
483 }
484 
createInstance(Context & context) const485 TestInstance* MultisampleRenderAreaTest::createInstance(Context& context) const
486 {
487 	return new MultisampleRenderAreaTestInstance(context, m_pipelineConstructionType, m_sampleCount, m_framebufferSize, m_testShape, m_colorFormat);
488 }
489 
checkSupport(Context & context) const490 void MultisampleRenderAreaTest::checkSupport(Context& context) const
491 {
492 	// Check support for MSAA image format used in the test.
493 	const InstanceInterface&	vki				= context.getInstanceInterface();
494 	const VkPhysicalDevice		physDevice		= context.getPhysicalDevice();
495 
496 	VkImageFormatProperties		formatProperties;
497 
498 	vki.getPhysicalDeviceImageFormatProperties	(physDevice, m_colorFormat,
499 												VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
500 												VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
501 												0u, &formatProperties);
502 
503 	if ((formatProperties.sampleCounts & m_sampleCount) == 0)
504 		TCU_THROW(NotSupportedError, "Format does not support this number of samples");
505 
506 	checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_pipelineConstructionType);
507 }
508 
509 } // anonymous
510 
createMultisampleResolveRenderpassRenderAreaTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)511 tcu::TestCaseGroup* createMultisampleResolveRenderpassRenderAreaTests(tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
512 {
513 	de::MovePtr<tcu::TestCaseGroup> testGroupResolve(new tcu::TestCaseGroup(testCtx, "resolve", "resolving multisample image tests"));
514 
515 	de::MovePtr<tcu::TestCaseGroup> testGroupRenderArea(new tcu::TestCaseGroup(testCtx, "renderpass_renderarea", "renderpass render area tests"));
516 
517 	static const struct
518 	{
519 		std::string					shapeName;
520 		TestShape					testShape;
521 	} shapes[]	=
522 	{
523 		{ "rectangle",		TestShape::SHAPE_RECTANGLE		},
524 		{ "diamond",		TestShape::SHAPE_DIAMOND		},
525 		{ "parallelogram",	TestShape::SHAPE_PARALLELOGRAM	}
526 	};
527 
528 	static const struct
529 	{
530 		std::string		caseName;
531 		const deUint32	sampleCount;
532 	} cases[]	=
533 	{
534 		{ "samples_2",	2u,	},
535 		{ "samples_4",	4u,	},
536 		{ "samples_8",	8u,	},
537 		{ "samples_16",	16u	},
538 	};
539 
540 	for (const auto& testShape : shapes)
541 	{
542 		for (const auto& testCase : cases)
543 		{
544 			testGroupRenderArea->addChild(new MultisampleRenderAreaTest(testCtx, testShape.shapeName + "_" + testCase.caseName, pipelineConstructionType, testCase.sampleCount, tcu::IVec2(32, 32), testShape.testShape));
545 		}
546 	}
547 
548 	testGroupResolve->addChild(testGroupRenderArea.release());
549 
550 	return testGroupResolve.release();
551 }
552 
553 } // pipeline
554 } // vkt
555