• 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 vktDrawMultisampleLinearInterpolationTests.cpp
22  * \brief InterpolateAt tests with linear interpolation
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktDrawMultisampleLinearInterpolationTests.hpp"
26 
27 #include "vktDrawBaseClass.hpp"
28 #include "vkQueryUtil.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkTypeUtil.hpp"
31 #include "vktTestGroupUtil.hpp"
32 
33 namespace vkt
34 {
35 namespace Draw
36 {
37 namespace
38 {
39 using namespace vk;
40 
41 class MultisampleLinearInterpolationTestInstance : public TestInstance
42 {
43 public:
MultisampleLinearInterpolationTestInstance(Context & context,const tcu::IVec2 renderSize,const float interpolationRange,const VkSampleCountFlagBits sampleCountFlagBits,const SharedGroupParams groupParams)44 						MultisampleLinearInterpolationTestInstance	(Context&						context,
45 																	 const tcu::IVec2				renderSize,
46 																	 const float					interpolationRange,
47 																	 const VkSampleCountFlagBits	sampleCountFlagBits,
48 																	 const SharedGroupParams		groupParams)
49 						: vkt::TestInstance		(context)
50 						, m_renderSize			(renderSize)
51 						, m_interpolationRange	(interpolationRange)
52 						, m_sampleCountFlagBits	(sampleCountFlagBits)
53 						, m_groupParams			(groupParams)
54 						{}
55 
~MultisampleLinearInterpolationTestInstance(void)56 						~MultisampleLinearInterpolationTestInstance	(void)
57 						{}
58 
59 	tcu::TestStatus		iterate										(void);
60 
61 private:
62 	const tcu::IVec2			m_renderSize;
63 	const float					m_interpolationRange;
64 	const VkSampleCountFlagBits	m_sampleCountFlagBits;
65 	const SharedGroupParams		m_groupParams;
66 };
67 
iterate(void)68 tcu::TestStatus MultisampleLinearInterpolationTestInstance::iterate (void)
69 {
70 	const DeviceInterface&						vk					= m_context.getDeviceInterface();
71 	const VkDevice								device				= m_context.getDevice();
72 
73 	tcu::ConstPixelBufferAccess					resultPixelBufferAccesses[2];
74 	de::SharedPtr<Image>						colorTargetImages[2];
75 	de::SharedPtr<Image>						multisampleImages[2];
76 
77 	const VkFormat								imageColorFormat	= VK_FORMAT_R8G8B8A8_UNORM;
78 
79 	const std::string							vertShadernames[2]	= { "vertRef", "vertNoPer" };
80 	const std::string							fragShadernames[2]	= { "fragRef", "fragNoPer" };
81 
82 	tcu::TestLog&								log					= m_context.getTestContext().getLog();
83 
84 	const bool									useMultisampling	= m_sampleCountFlagBits == VK_SAMPLE_COUNT_1_BIT ? false : true;
85 
86 	for (int draw = 0; draw < 2; draw++)
87 	{
88 		const Unique<VkShaderModule>					vs					(createShaderModule(vk, device, m_context.getBinaryCollection().get(vertShadernames[draw].c_str()), 0));
89 		const Unique<VkShaderModule>					fs					(createShaderModule(vk, device, m_context.getBinaryCollection().get(fragShadernames[draw].c_str()), 0));
90 
91 		de::SharedPtr<Buffer>							vertexBuffer;
92 
93 		const CmdPoolCreateInfo							cmdPoolCreateInfo	(m_context.getUniversalQueueFamilyIndex());
94 		Move<VkCommandPool>								cmdPool				= createCommandPool(vk, device, &cmdPoolCreateInfo);
95 		Move<VkCommandBuffer>							cmdBuffer			= allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
96 		Move<VkCommandBuffer>							secCmdBuffer;
97 
98 		Move<VkRenderPass>								renderPass;
99 
100 		std::vector<Move<VkImageView>>					colorTargetViews;
101 		std::vector<Move<VkImageView>>					multisampleViews;
102 
103 		Move<VkFramebuffer>								framebuffer;
104 
105 		Move<VkPipeline>								pipeline;
106 		const PipelineLayoutCreateInfo					pipelineLayoutCreateInfo;
107 		Move<VkPipelineLayout>							pipelineLayout		= createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
108 
109 		const VkVertexInputAttributeDescription			vertInAttrDescs[2]	=
110 		{
111 			{ 0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u },
112 			{ 1u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, static_cast<deUint32>(sizeof(float) * 4) }
113 		};
114 
115 		// Create color buffer images
116 		{
117 			const VkExtent3D		targetImageExtent		= { static_cast<deUint32>(m_renderSize.x()), static_cast<deUint32>(m_renderSize.y()), 1u };
118 			const VkImageUsageFlags	usage					= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
119 			const ImageCreateInfo	targetImageCreateInfo	(VK_IMAGE_TYPE_2D,
120 															 imageColorFormat,
121 															 targetImageExtent,
122 															 1u,
123 															 1u,
124 															 VK_SAMPLE_COUNT_1_BIT,
125 															 VK_IMAGE_TILING_OPTIMAL,
126 															 usage);
127 
128 			colorTargetImages[draw] = Image::createAndAlloc(vk, device, targetImageCreateInfo,
129 															m_context.getDefaultAllocator(),
130 															m_context.getUniversalQueueFamilyIndex());
131 
132 			if (useMultisampling)
133 			{
134 				const ImageCreateInfo	multisampleImageCreateInfo	(VK_IMAGE_TYPE_2D,
135 																	 imageColorFormat,
136 																	 targetImageExtent,
137 																	 1u,
138 																	 1u,
139 																	 m_sampleCountFlagBits,
140 																	 VK_IMAGE_TILING_OPTIMAL,
141 																	 usage);
142 
143 				multisampleImages[draw] = Image::createAndAlloc(vk, device, multisampleImageCreateInfo,
144 																m_context.getDefaultAllocator(),
145 																m_context.getUniversalQueueFamilyIndex());
146 			}
147 		}
148 
149 		{
150 			const ImageViewCreateInfo colorTargetViewInfo(colorTargetImages[draw]->object(),
151 														  VK_IMAGE_VIEW_TYPE_2D,
152 														  imageColorFormat);
153 
154 			colorTargetViews.push_back(createImageView(vk, device, &colorTargetViewInfo));
155 
156 			if (useMultisampling)
157 			{
158 				const ImageViewCreateInfo multisamplingTargetViewInfo(multisampleImages[draw]->object(),
159 																	  VK_IMAGE_VIEW_TYPE_2D,
160 																	  imageColorFormat);
161 
162 				multisampleViews.push_back(createImageView(vk, device, &multisamplingTargetViewInfo));
163 			}
164 		}
165 
166 		// Create render pass and frame buffer.
167 		if (!m_groupParams->useDynamicRendering)
168 		{
169 			RenderPassCreateInfo				renderPassCreateInfo;
170 			std::vector<VkImageView>			attachments;
171 			std::vector<VkAttachmentReference>	colorAttachmentRefs;
172 			std::vector<VkAttachmentReference>	multisampleAttachmentRefs;
173 			deUint32							attachmentNdx		= 0;
174 
175 			{
176 				const VkAttachmentReference	colorAttachmentReference	=
177 				{
178 					attachmentNdx++,							// uint32_t			attachment;
179 					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout	layout;
180 				};
181 
182 				colorAttachmentRefs.push_back(colorAttachmentReference);
183 
184 				renderPassCreateInfo.addAttachment(AttachmentDescription(imageColorFormat,
185 																		 VK_SAMPLE_COUNT_1_BIT,
186 																		 VK_ATTACHMENT_LOAD_OP_CLEAR,
187 																		 VK_ATTACHMENT_STORE_OP_STORE,
188 																		 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
189 																		 VK_ATTACHMENT_STORE_OP_DONT_CARE,
190 																		 VK_IMAGE_LAYOUT_UNDEFINED,
191 																		 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL));
192 
193 				if (useMultisampling)
194 				{
195 					const VkAttachmentReference	multiSampleAttachmentReference	=
196 					{
197 						attachmentNdx++,							// uint32_t			attachment;
198 						VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout	layout;
199 					};
200 
201 					multisampleAttachmentRefs.push_back(multiSampleAttachmentReference);
202 
203 					renderPassCreateInfo.addAttachment(AttachmentDescription(imageColorFormat,
204 																			 m_sampleCountFlagBits,
205 																			 VK_ATTACHMENT_LOAD_OP_CLEAR,
206 																			 VK_ATTACHMENT_STORE_OP_DONT_CARE,
207 																			 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
208 																			 VK_ATTACHMENT_STORE_OP_DONT_CARE,
209 																			 VK_IMAGE_LAYOUT_UNDEFINED,
210 																			 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
211 				}
212 			}
213 
214 			renderPassCreateInfo.addSubpass(SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS,
215 															   0,
216 															   0,
217 															   DE_NULL,
218 															   (deUint32)colorAttachmentRefs.size(),
219 															   useMultisampling ? &multisampleAttachmentRefs[0] : &colorAttachmentRefs[0],
220 															   useMultisampling ? &colorAttachmentRefs[0] : DE_NULL,
221 															   AttachmentReference(),
222 															   0,
223 															   DE_NULL));
224 
225 			renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
226 
227 			for (deUint32 frameNdx = 0; frameNdx < colorTargetViews.size(); frameNdx++)
228 			{
229 				attachments.push_back(*colorTargetViews[frameNdx]);
230 
231 				if (useMultisampling)
232 					attachments.push_back(*multisampleViews[frameNdx]);
233 			}
234 
235 			const VkFramebufferCreateInfo	framebufferCreateInfo	=
236 			{
237 				VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// VkStructureType			sType;
238 				DE_NULL,									// const void*				pNext;
239 				0u,											// VkFramebufferCreateFlags	flags;
240 				*renderPass,								// VkRenderPass				renderPass;
241 				static_cast<deUint32>(attachments.size()),	// uint32_t					attachmentCount;
242 				&attachments[0],							// const VkImageView*		pAttachments;
243 				static_cast<deUint32>(m_renderSize.x()),	// uint32_t					width;
244 				static_cast<deUint32>(m_renderSize.y()),	// uint32_t					height;
245 				1u											// uint32_t					layers;
246 			};
247 
248 			framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
249 		}
250 
251 		// Create vertex buffer.
252 		{
253 			const PositionColorVertex	vertices[]		=
254 			{
255 				// The first draw is for reference image.
256 				/*     ____            ____   */
257 				/*    /    \          |    |  */
258 				/*   /      \         |____|  */
259 				/*  /        \                */
260 				/* /__________\               */
261 				/*                            */
262 				/*    result        reference */
263 				/*                            */
264 				// In result shape the bottom vertices are deeper. When the drawn result image is a perfect square,
265 				// and color comparison with reference image is easy to make.
266 				PositionColorVertex(tcu::Vec4(	1.0f,						-1.0f,						0.0f,	1.0f),						tcu::Vec4(0.0f, m_interpolationRange, 0.0f, m_interpolationRange)),	// Top Right
267 				PositionColorVertex(tcu::Vec4(	-1.0f,						-1.0f,						0.0f,	1.0f),						tcu::Vec4(m_interpolationRange * 0.5f, m_interpolationRange * 0.5f, 0.0f, m_interpolationRange)),	// Top Left
268 				PositionColorVertex(tcu::Vec4(	draw == 0 ? 1.0f : 2.0f,	draw == 0 ? 1.0f : 2.0f,	0.0f,	draw == 0 ? 1.0f : 2.0f),	tcu::Vec4(m_interpolationRange * 0.5f, m_interpolationRange * 0.5f, 0.0f, m_interpolationRange)),	// Bottom Right
269 				PositionColorVertex(tcu::Vec4(	draw == 0 ? -1.0f : -2.0f,	draw == 0 ? 1.0f : 2.0f,	0.0f,	draw == 0 ? 1.0f : 2.0f),	tcu::Vec4(m_interpolationRange, 0.0f, 0.0f, m_interpolationRange)),	// Bottom Left
270 				PositionColorVertex(tcu::Vec4(	draw == 0 ? 1.0f : 2.0f,	draw == 0 ? 1.0f : 2.0f,	0.0f,	draw == 0 ? 1.0f : 2.0f),	tcu::Vec4(m_interpolationRange * 0.5f, m_interpolationRange * 0.5f, 0.0f, m_interpolationRange)),	// Bottom Right
271 				PositionColorVertex(tcu::Vec4(	-1.0f,						-1.0f,						0.0f,	1.0f),						tcu::Vec4(m_interpolationRange * 0.5f, m_interpolationRange * 0.5f, 0.0f, m_interpolationRange))	// Top Left
272 			};
273 
274 			const VkDeviceSize			dataSize		= sizeof(vertices);
275 										vertexBuffer	= Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
276 			deUint8*					ptr				= static_cast<deUint8*>(vertexBuffer->getBoundMemory().getHostPtr());
277 
278 			deMemcpy(ptr, vertices, static_cast<size_t>(dataSize));
279 			flushMappedMemoryRange(vk, device, vertexBuffer->getBoundMemory().getMemory(), vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
280 		}
281 
282 		// Create pipeline.
283 		{
284 			const PipelineCreateInfo::ColorBlendState::Attachment	vkCbAttachmentState;
285 
286 			VkViewport												viewport						= makeViewport(m_renderSize.x(), m_renderSize.y());
287 			VkRect2D												scissor							= makeRect2D(m_renderSize.x(), m_renderSize.y());
288 
289 			const std::vector<deUint32>								sampleMask						= { 0xfffffff, 0xfffffff };
290 
291 			const VkVertexInputBindingDescription					vertexInputBindingDescription	= { 0, (deUint32)sizeof(tcu::Vec4) * 2, VK_VERTEX_INPUT_RATE_VERTEX };
292 			PipelineCreateInfo::VertexInputState					vertexInputState				= PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription, 2, vertInAttrDescs);
293 
294 			PipelineCreateInfo										pipelineCreateInfo(*pipelineLayout, *renderPass, 0, 0);
295 
296 			pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", VK_SHADER_STAGE_VERTEX_BIT));
297 			pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
298 			pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(vertexInputState));
299 			pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
300 			pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
301 			pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, std::vector<VkViewport>(1, viewport), std::vector<VkRect2D>(1, scissor)));
302 			pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
303 			pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
304 			pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState(m_sampleCountFlagBits, false, 0.0f, sampleMask));
305 
306 #ifndef CTS_USES_VULKANSC
307 			VkPipelineRenderingCreateInfo							renderingCreateInfo
308 			{
309 				VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
310 				DE_NULL,
311 				0u,
312 				1u,
313 				&imageColorFormat,
314 				VK_FORMAT_UNDEFINED,
315 				VK_FORMAT_UNDEFINED
316 			};
317 
318 			if (m_groupParams->useDynamicRendering)
319 				pipelineCreateInfo.pNext = &renderingCreateInfo;
320 #endif // CTS_USES_VULKANSC
321 
322 			pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
323 		}
324 
325 		// Draw quad and read results.
326 		{
327 			const VkQueue					queue				= m_context.getUniversalQueue();
328 			const VkClearValue				clearColor			= { { { 0.0f, 0.0f, 0.0f, 1.0f } } };
329 			const ImageSubresourceRange		subresourceRange	(VK_IMAGE_ASPECT_COLOR_BIT);
330 			const VkRect2D					renderArea			= makeRect2D(m_renderSize.x(), m_renderSize.y());
331 			const VkBuffer					buffer				= vertexBuffer->object();
332 			const VkOffset3D				zeroOffset			= { 0, 0, 0 };
333 
334 			std::vector<VkClearValue>		clearValues			(2, clearColor);
335 
336 			auto drawCommands = [&](VkCommandBuffer cmdBuff)
337 			{
338 				const VkDeviceSize vertexBufferOffset = 0;
339 				vk.cmdBindVertexBuffers(cmdBuff, 0, 1, &buffer, &vertexBufferOffset);
340 				vk.cmdBindPipeline(cmdBuff, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
341 				vk.cmdDraw(cmdBuff, 6u, 1u, 0u, 0u);
342 			};
343 
344 			clearColorImage(vk, device, queue, m_context.getUniversalQueueFamilyIndex(),
345 				colorTargetImages[draw]->object(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
346 				VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
347 				VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 1u);
348 
349 #ifndef CTS_USES_VULKANSC
350 			auto preRenderBarriers = [&]()
351 			{
352 				// Transition Images
353 				initialTransitionColor2DImage(vk, *cmdBuffer, colorTargetImages[draw]->object(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
354 					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
355 
356 				if (useMultisampling)
357 				{
358 					initialTransitionColor2DImage(vk, *cmdBuffer, multisampleImages[draw]->object(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
359 						VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
360 				}
361 			};
362 
363 			if (m_groupParams->useDynamicRendering)
364 			{
365 				const deUint32 imagesCount = static_cast<deUint32>(colorTargetViews.size());
366 
367 				std::vector<VkRenderingAttachmentInfo> colorAttachments(imagesCount,
368 				{
369 					VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,	// VkStructureType			sType;
370 					DE_NULL,											// const void*				pNext;
371 					DE_NULL,											// VkImageView				imageView;
372 					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout			imageLayout;
373 					VK_RESOLVE_MODE_NONE,								// VkResolveModeFlagBits	resolveMode;
374 					DE_NULL,											// VkImageView				resolveImageView;
375 					VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout			resolveImageLayout;
376 					VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp		loadOp;
377 					VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp		storeOp;
378 					clearColor											// VkClearValue				clearValue;
379 				});
380 
381 				for (deUint32 i = 0; i < imagesCount; ++i)
382 				{
383 					if (useMultisampling)
384 					{
385 						colorAttachments[i].imageView			= *multisampleViews[i];
386 						colorAttachments[i].resolveMode			= VK_RESOLVE_MODE_AVERAGE_BIT;
387 						colorAttachments[i].resolveImageView	= *colorTargetViews[i];
388 					}
389 					else
390 					{
391 						colorAttachments[i].imageView			= *colorTargetViews[i];
392 					}
393 				}
394 
395 				VkRenderingInfo renderingInfo
396 				{
397 					VK_STRUCTURE_TYPE_RENDERING_INFO,	// VkStructureType						sType;
398 					DE_NULL,							// const void*							pNext;
399 					0,									// VkRenderingFlagsKHR					flags;
400 					renderArea,							// VkRect2D								renderArea;
401 					1u,									// deUint32								layerCount;
402 					0u,									// deUint32								viewMask;
403 					imagesCount,						// deUint32								colorAttachmentCount;
404 					colorAttachments.data(),			// const VkRenderingAttachmentInfoKHR*	pColorAttachments;
405 					DE_NULL,							// const VkRenderingAttachmentInfoKHR*	pDepthAttachment;
406 					DE_NULL,							// const VkRenderingAttachmentInfoKHR*	pStencilAttachment;
407 				};
408 
409 				if (m_groupParams->useSecondaryCmdBuffer)
410 				{
411 					VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
412 					{
413 						VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR,		// VkStructureType						sType;
414 						DE_NULL,																// const void*							pNext;
415 						0u,																		// VkRenderingFlagsKHR					flags;
416 						0u,																		// uint32_t								viewMask;
417 						1u,																		// uint32_t								colorAttachmentCount;
418 						&imageColorFormat,														// const VkFormat*						pColorAttachmentFormats;
419 						VK_FORMAT_UNDEFINED,													// VkFormat								depthAttachmentFormat;
420 						VK_FORMAT_UNDEFINED,													// VkFormat								stencilAttachmentFormat;
421 						m_sampleCountFlagBits													// VkSampleCountFlagBits				rasterizationSamples;
422 					};
423 
424 					const VkCommandBufferInheritanceInfo	bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
425 					VkCommandBufferBeginInfo				commandBufBeginParams
426 					{
427 						VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,							// VkStructureType					sType;
428 						DE_NULL,																// const void*						pNext;
429 						VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,							// VkCommandBufferUsageFlags		flags;
430 						&bufferInheritanceInfo
431 					};
432 
433 					secCmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
434 
435 					// record secondary command buffer
436 					if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
437 					{
438 						inheritanceRenderingInfo.flags = VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT;
439 						VK_CHECK(vk.beginCommandBuffer(*secCmdBuffer, &commandBufBeginParams));
440 						vk.cmdBeginRendering(*secCmdBuffer, &renderingInfo);
441 					}
442 					else
443 					{
444 						commandBufBeginParams.flags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
445 						VK_CHECK(vk.beginCommandBuffer(*secCmdBuffer, &commandBufBeginParams));
446 					}
447 
448 					drawCommands(*secCmdBuffer);
449 
450 					if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
451 						endRendering(vk, *secCmdBuffer);
452 
453 					endCommandBuffer(vk, *secCmdBuffer);
454 
455 					// record primary command buffer
456 					beginCommandBuffer(vk, *cmdBuffer, 0u);
457 
458 					preRenderBarriers();
459 
460 					if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
461 					{
462 						renderingInfo.flags = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
463 						vk.cmdBeginRendering(*cmdBuffer, &renderingInfo);
464 					}
465 					vk.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffer);
466 
467 					if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
468 						endRendering(vk, *cmdBuffer);
469 					endCommandBuffer(vk, *cmdBuffer);
470 				}
471 				else
472 				{
473 					beginCommandBuffer(vk, *cmdBuffer, 0u);
474 					preRenderBarriers();
475 
476 					vk.cmdBeginRendering(*cmdBuffer, &renderingInfo);
477 					drawCommands(*cmdBuffer);
478 					endRendering(vk, *cmdBuffer);
479 
480 					endCommandBuffer(vk, *cmdBuffer);
481 				}
482 			}
483 			else
484 #endif // CTS_USES_VULKANSC
485 			{
486 				beginCommandBuffer(vk, *cmdBuffer, 0u);
487 
488 				const deUint32 imagesCount = static_cast<deUint32>(colorTargetViews.size() + multisampleViews.size());
489 
490 				beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, imagesCount, &clearValues[0]);
491 				drawCommands(*cmdBuffer);
492 				endRenderPass(vk, *cmdBuffer);
493 
494 				endCommandBuffer(vk, *cmdBuffer);
495 			}
496 
497 			submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
498 
499 			resultPixelBufferAccesses[draw] = colorTargetImages[draw]->readSurface(queue, m_context.getDefaultAllocator(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, zeroOffset, m_renderSize.x(), m_renderSize.y(), VK_IMAGE_ASPECT_COLOR_BIT);
500 		}
501 	}
502 
503 	if (!tcu::floatThresholdCompare(log, "Result", "Image comparison result", resultPixelBufferAccesses[0], resultPixelBufferAccesses[1], tcu::Vec4(0.005f), tcu::COMPARE_LOG_RESULT))
504 		return tcu::TestStatus::fail("Rendered color image is not correct");
505 
506 	return tcu::TestStatus::pass("Success");
507 }
508 
509 class MultisampleLinearInterpolationTestCase : public TestCase
510 {
511 	public:
MultisampleLinearInterpolationTestCase(tcu::TestContext & context,const char * name,const char * desc,const tcu::IVec2 renderSize,const float interpolationRange,const tcu::Vec2 offset,const VkSampleCountFlagBits sampleCountFlagBits,const SharedGroupParams groupParams)512 								MultisampleLinearInterpolationTestCase	(tcu::TestContext&				context,
513 																		 const char*					name,
514 																		 const char*					desc,
515 																		 const tcu::IVec2				renderSize,
516 																		 const float					interpolationRange,
517 																		 const tcu::Vec2				offset,
518 																		 const VkSampleCountFlagBits	sampleCountFlagBits,
519 																		 const SharedGroupParams		groupParams)
520 								: vkt::TestCase(context, name, desc)
521 								, m_renderSize			(renderSize)
522 								, m_interpolationRange	(interpolationRange)
523 								, m_offset				(offset)
524 								, m_sampleCountFlagBits	(sampleCountFlagBits)
525 								, m_groupParams			(groupParams)
526 								{}
527 
~MultisampleLinearInterpolationTestCase(void)528 								~MultisampleLinearInterpolationTestCase	(void)
529 								{}
530 
531 	virtual	void				initPrograms		(SourceCollections& programCollection) const;
532 	virtual void				checkSupport		(Context& context) const;
533 	virtual TestInstance*		createInstance		(Context& context) const;
534 
535 private:
536 	const tcu::IVec2			m_renderSize;
537 	const float					m_interpolationRange;
538 	const tcu::Vec2				m_offset;
539 	const VkSampleCountFlagBits	m_sampleCountFlagBits;
540 	const SharedGroupParams		m_groupParams;
541 };
542 
initPrograms(SourceCollections & programCollection) const543 void MultisampleLinearInterpolationTestCase::initPrograms (SourceCollections& programCollection) const
544 {
545 	// Reference vertex shader.
546 	{
547 		std::ostringstream vrt;
548 
549 		vrt << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
550 			<< "\n"
551 			<< "layout(location = 0) in vec4 in_position;\n"
552 			<< "layout(location = 1) in vec4 in_color;\n"
553 			<< "layout(location = 0) out vec4 out_color;\n"
554 			<< "\n"
555 			<< "void main()\n"
556 			<< "{\n"
557 			<< "    gl_PointSize = 1.0;\n"
558 			<< "    gl_Position  = in_position;\n"
559 			<< "    out_color    = in_color;\n"
560 			<< "}\n";
561 
562 		programCollection.glslSources.add("vertRef") << glu::VertexSource(vrt.str());
563 	}
564 
565 	// Noperspective vertex shader.
566 	{
567 		std::ostringstream vrt;
568 
569 		vrt << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
570 			<< "\n"
571 			<< "layout(location = 0) in vec4 in_position;\n"
572 			<< "layout(location = 1) in vec4 in_color;\n"
573 			<< "layout(location = 0) noperspective out vec4 out_color;\n"
574 			<< "\n"
575 			<< "void main()\n"
576 			<< "{\n"
577 			<< "    gl_PointSize = 1.0;\n"
578 			<< "    gl_Position  = in_position;\n"
579 			<< "    out_color    = in_color;\n"
580 			<< "}\n";
581 
582 		programCollection.glslSources.add("vertNoPer") << glu::VertexSource(vrt.str());
583 	}
584 
585 	// Reference fragment shader.
586 	{
587 		std::ostringstream frg;
588 
589 		frg << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
590 			<< "layout(location = 0) in vec4 in_color;\n"
591 			<< "layout(location = 0) out vec4 out_color;\n"
592 			<< "void main()\n"
593 			<< "{\n"
594 			<< "    vec4 out_color_y = mix(vec4(0.0, 1.0, 0.0, 1.0), vec4(1.0, 0.0, 0.0, 1.0), gl_FragCoord.y / " << static_cast<float>(m_renderSize.y()) << " + " << m_offset.y() / static_cast<float>(m_renderSize.y()) << ");\n"
595 			<< "    vec4 out_color_x = mix(vec4(1.0, 0.0, 0.0, 1.0), vec4(0.0, 1.0, 0.0, 1.0), gl_FragCoord.x / " << static_cast<float>(m_renderSize.x()) << " + " << m_offset.x() / static_cast<float>(m_renderSize.x()) << ");\n"
596 			<< "    out_color = 0.5 * (out_color_y + out_color_x);\n"
597 			<< "}\n";
598 
599 		programCollection.glslSources.add("fragRef") << glu::FragmentSource(frg.str());
600 	}
601 
602 	// Noperspective fragment shader.
603 	{
604 		std::ostringstream frg;
605 
606 		frg << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
607 			<< "layout(location = 0) noperspective in vec4 in_color;\n"
608 			<< "layout(location = 0) out vec4 out_color;\n"
609 			<< "void main()\n"
610 			<< "{\n"
611 			<< "    vec4 out_color_offset = interpolateAtOffset(in_color, vec2(" << m_offset.x() << ", " << m_offset.y() << "));\n"
612 			<< "    vec4 out_color_sample = interpolateAtSample(in_color, gl_SampleID);\n"
613 			<< "    out_color = (0.5 * (out_color_offset + out_color_sample));\n"
614 			<< "    out_color /= " << m_interpolationRange << ";\n";
615 
616 		// Run additional sample comparison test. If it fails, we write 1.0 to blue color channel.
617 		frg << "    vec4 diff = out_color_sample - interpolateAtOffset(in_color, gl_SamplePosition - vec2(0.5));"
618 			<< "    float min_precision = 0.000001;\n"
619 			<< "    if (diff.x > min_precision && diff.y > min_precision && diff.z > min_precision && diff.w > min_precision)\n"
620 			<< "    {\n"
621 			<< "        out_color.z = 1.0;\n"
622 			<< "    }\n";
623 
624 		frg << "}\n";
625 
626 		programCollection.glslSources.add("fragNoPer") << glu::FragmentSource(frg.str());
627 	}
628 }
629 
checkSupport(Context & context) const630 void MultisampleLinearInterpolationTestCase::checkSupport (Context& context) const
631 {
632 	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
633 
634 	if (!(m_sampleCountFlagBits & context.getDeviceProperties().limits.framebufferColorSampleCounts))
635 		TCU_THROW(NotSupportedError, "Multisampling with " + de::toString(m_sampleCountFlagBits) + " samples not supported");
636 
637 #ifndef CTS_USES_VULKANSC
638 	if (m_groupParams->useDynamicRendering)
639 		context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
640 
641 	if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
642 		!context.getPortabilitySubsetFeatures().shaderSampleRateInterpolationFunctions)
643 	{
644 		TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Shader sample rate interpolation functions are not supported by this implementation");
645 	}
646 #endif // CTS_USES_VULKANSC
647 }
648 
createInstance(Context & context) const649 TestInstance* MultisampleLinearInterpolationTestCase::createInstance (Context& context) const
650 {
651 	return new MultisampleLinearInterpolationTestInstance(context, m_renderSize, m_interpolationRange, m_sampleCountFlagBits, m_groupParams);
652 }
653 
createTests(tcu::TestCaseGroup * testGroup,const SharedGroupParams groupParams)654 void createTests (tcu::TestCaseGroup* testGroup, const SharedGroupParams groupParams)
655 {
656 	tcu::TestContext&	testCtx	= testGroup->getTestContext();
657 
658 	struct
659 	{
660 		const std::string	name;
661 		const tcu::Vec2		value;
662 	} offsets[]	=
663 	{
664 		{ "no_offset",	tcu::Vec2(0.0f, 0.0f) },
665 		{ "offset_min",	tcu::Vec2(-0.5f, -0.5f) },
666 		{ "offset_max",	tcu::Vec2(0.4375f, 0.4375f) }
667 	};
668 
669 	struct
670 	{
671 		const std::string		name;
672 		VkSampleCountFlagBits	value;
673 	} flagBits[] =
674 	{
675 		{ "1_sample",	VK_SAMPLE_COUNT_1_BIT },
676 		{ "2_samples",	VK_SAMPLE_COUNT_2_BIT },
677 		{ "4_samples",	VK_SAMPLE_COUNT_4_BIT },
678 		{ "8_samples",	VK_SAMPLE_COUNT_8_BIT },
679 		{ "16_samples",	VK_SAMPLE_COUNT_16_BIT },
680 		{ "32_samples",	VK_SAMPLE_COUNT_32_BIT },
681 		{ "64_samples",	VK_SAMPLE_COUNT_64_BIT }
682 	};
683 
684 	for (const auto& offset : offsets)
685 	{
686 		for (const auto& flagBit : flagBits)
687 		{
688 			// reduce number of tests for dynamic rendering cases where secondary command buffer is used
689 			if (groupParams->useSecondaryCmdBuffer && (flagBit.value > VK_SAMPLE_COUNT_4_BIT))
690 				break;
691 
692 			testGroup->addChild(new MultisampleLinearInterpolationTestCase(testCtx, (offset.name + "_" + flagBit.name).c_str(), ".", tcu::IVec2(16, 16), 1.0f, offset.value, flagBit.value, groupParams));
693 		}
694 	}
695 }
696 
697 }	// anonymous
698 
createMultisampleLinearInterpolationTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)699 tcu::TestCaseGroup*	createMultisampleLinearInterpolationTests (tcu::TestContext& testCtx, const SharedGroupParams groupParams)
700 {
701 	return createTestGroup(testCtx, "linear_interpolation", "Tests for linear interpolation decorations.", createTests, groupParams);
702 }
703 
704 }	// Draw
705 }	// vkt
706