• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  * Copyright (c) 2015 The Khronos Group 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
22  * \brief Early fragment tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktFragmentOperationsEarlyFragmentTests.hpp"
26 #include "vktTestCaseUtil.hpp"
27 
28 #include "vkDefs.hpp"
29 #include "vkRef.hpp"
30 #include "vkRefUtil.hpp"
31 #include "vkPlatform.hpp"
32 #include "vkPrograms.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkStrUtil.hpp"
36 #include "vkTypeUtil.hpp"
37 #include "vkQueryUtil.hpp"
38 #include "vkImageUtil.hpp"
39 #include "vkBarrierUtil.hpp"
40 #include "vkCmdUtil.hpp"
41 #include "vkObjUtil.hpp"
42 
43 #include "tcuTestLog.hpp"
44 #include "tcuImageCompare.hpp"
45 #include "tcuTextureUtil.hpp"
46 
47 #include "deUniquePtr.hpp"
48 #include "deStringUtil.hpp"
49 #include "deMath.h"
50 
51 #include <string>
52 
53 namespace vkt
54 {
55 namespace FragmentOperations
56 {
57 namespace
58 {
59 using namespace vk;
60 using de::UniquePtr;
61 
62 //! Basic 2D image.
makeImageCreateInfo(const tcu::IVec2 & size,const VkFormat format,const VkImageUsageFlags usage)63 inline VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage)
64 {
65 	const VkImageCreateInfo imageParams =
66 	{
67 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,					// VkStructureType			sType;
68 		DE_NULL,												// const void*				pNext;
69 		(VkImageCreateFlags)0,									// VkImageCreateFlags		flags;
70 		VK_IMAGE_TYPE_2D,										// VkImageType				imageType;
71 		format,													// VkFormat					format;
72 		makeExtent3D(size.x(), size.y(), 1),					// VkExtent3D				extent;
73 		1u,														// deUint32					mipLevels;
74 		1u,														// deUint32					arrayLayers;
75 		VK_SAMPLE_COUNT_1_BIT,									// VkSampleCountFlagBits	samples;
76 		VK_IMAGE_TILING_OPTIMAL,								// VkImageTiling			tiling;
77 		usage,													// VkImageUsageFlags		usage;
78 		VK_SHARING_MODE_EXCLUSIVE,								// VkSharingMode			sharingMode;
79 		0u,														// deUint32					queueFamilyIndexCount;
80 		DE_NULL,												// const deUint32*			pQueueFamilyIndices;
81 		VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout			initialLayout;
82 	};
83 	return imageParams;
84 }
85 
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const bool useDepthStencilAttachment,const VkFormat depthStencilFormat)86 Move<VkRenderPass> makeRenderPass (const DeviceInterface&	vk,
87 								   const VkDevice			device,
88 								   const VkFormat			colorFormat,
89 								   const bool				useDepthStencilAttachment,
90 								   const VkFormat			depthStencilFormat)
91 {
92 	return makeRenderPass(vk, device, colorFormat, useDepthStencilAttachment ? depthStencilFormat : VK_FORMAT_UNDEFINED);
93 }
94 
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const tcu::IVec2 & renderSize,const bool enableDepthTest,const bool enableStencilTest,const VkStencilOp stencilFailOp=VK_STENCIL_OP_KEEP,const VkStencilOp stencilPassOp=VK_STENCIL_OP_KEEP)95 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&	vk,
96 									   const VkDevice			device,
97 									   const VkPipelineLayout	pipelineLayout,
98 									   const VkRenderPass		renderPass,
99 									   const VkShaderModule		vertexModule,
100 									   const VkShaderModule		fragmentModule,
101 									   const tcu::IVec2&		renderSize,
102 									   const bool				enableDepthTest,
103 									   const bool				enableStencilTest,
104 									   const VkStencilOp		stencilFailOp = VK_STENCIL_OP_KEEP,
105 									   const VkStencilOp		stencilPassOp = VK_STENCIL_OP_KEEP)
106 {
107 	const std::vector<VkViewport>			viewports					(1, makeViewport(renderSize));
108 	const std::vector<VkRect2D>				scissors					(1, makeRect2D(renderSize));
109 
110 	const VkStencilOpState					stencilOpState				= makeStencilOpState(
111 		stencilFailOp,			// stencil fail
112 		stencilPassOp,			// depth & stencil pass
113 		VK_STENCIL_OP_KEEP,		// depth only fail
114 		VK_COMPARE_OP_EQUAL,	// compare op
115 		0x3,					// compare mask
116 		0xf,					// write mask
117 		1u);					// reference
118 
119 	VkPipelineDepthStencilStateCreateInfo	depthStencilStateCreateInfo	=
120 	{
121 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType                          sType
122 		DE_NULL,													// const void*                              pNext
123 		0u,															// VkPipelineDepthStencilStateCreateFlags   flags
124 		enableDepthTest ? VK_TRUE : VK_FALSE,						// VkBool32                                 depthTestEnable
125 		enableDepthTest ? VK_TRUE : VK_FALSE,						// VkBool32                                 depthWriteEnable
126 		VK_COMPARE_OP_LESS,											// VkCompareOp                              depthCompareOp
127 		VK_FALSE,													// VkBool32                                 depthBoundsTestEnable
128 		enableStencilTest ? VK_TRUE : VK_FALSE,						// VkBool32                                 stencilTestEnable
129 		stencilOpState,												// VkStencilOpState                         front
130 		stencilOpState,												// VkStencilOpState                         back
131 		0.0f,														// float                                    minDepthBounds
132 		1.0f														// float                                    maxDepthBounds
133 	};
134 
135 	return vk::makeGraphicsPipeline(vk,										// const DeviceInterface&                        vk
136 									device,									// const VkDevice                                device
137 									pipelineLayout,							// const VkPipelineLayout                        pipelineLayout
138 									vertexModule,							// const VkShaderModule                          vertexShaderModule
139 									DE_NULL,								// const VkShaderModule                          tessellationControlModule
140 									DE_NULL,								// const VkShaderModule                          tessellationEvalModule
141 									DE_NULL,								// const VkShaderModule                          geometryShaderModule
142 									fragmentModule,							// const VkShaderModule                          fragmentShaderModule
143 									renderPass,								// const VkRenderPass                            renderPass
144 									viewports,								// const std::vector<VkViewport>&                viewports
145 									scissors,								// const std::vector<VkRect2D>&                  scissors
146 									VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology                     topology
147 									0u,										// const deUint32                                subpass
148 									0u,										// const deUint32                                patchControlPoints
149 									DE_NULL,								// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
150 									DE_NULL,								// const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
151 									DE_NULL,								// const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
152 									&depthStencilStateCreateInfo);			// const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
153 }
154 
commandClearStencilAttachment(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const VkOffset2D & offset,const VkExtent2D & extent,const deUint32 clearValue)155 void commandClearStencilAttachment (const DeviceInterface&	vk,
156 									const VkCommandBuffer	commandBuffer,
157 									const VkOffset2D&		offset,
158 									const VkExtent2D&		extent,
159 									const deUint32			clearValue)
160 {
161 	const VkClearAttachment stencilAttachment =
162 	{
163 		VK_IMAGE_ASPECT_STENCIL_BIT,					// VkImageAspectFlags    aspectMask;
164 		0u,												// uint32_t              colorAttachment;
165 		makeClearValueDepthStencil(0.0f, clearValue),	// VkClearValue          clearValue;
166 	};
167 
168 	const VkClearRect rect =
169 	{
170 		{ offset, extent },		// VkRect2D    rect;
171 		0u,						// uint32_t    baseArrayLayer;
172 		1u,						// uint32_t    layerCount;
173 	};
174 
175 	vk.cmdClearAttachments(commandBuffer, 1u, &stencilAttachment, 1u, &rect);
176 }
177 
getImageAspectFlags(const VkFormat format)178 VkImageAspectFlags getImageAspectFlags (const VkFormat format)
179 {
180 	const tcu::TextureFormat tcuFormat = mapVkFormat(format);
181 
182 	if      (tcuFormat.order == tcu::TextureFormat::DS)		return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
183 	else if (tcuFormat.order == tcu::TextureFormat::D)		return VK_IMAGE_ASPECT_DEPTH_BIT;
184 	else if (tcuFormat.order == tcu::TextureFormat::S)		return VK_IMAGE_ASPECT_STENCIL_BIT;
185 
186 	DE_ASSERT(false);
187 	return 0u;
188 }
189 
isSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,const VkPhysicalDevice device,const VkFormat format)190 bool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, const VkPhysicalDevice device, const VkFormat format)
191 {
192 	VkFormatProperties formatProps;
193 	instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
194 	return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
195 }
196 
pickSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,const VkPhysicalDevice device,const deUint32 numFormats,const VkFormat * pFormats)197 VkFormat pickSupportedDepthStencilFormat (const InstanceInterface&	instanceInterface,
198 										  const VkPhysicalDevice	device,
199 										  const deUint32			numFormats,
200 										  const VkFormat*			pFormats)
201 {
202 	for (deUint32 i = 0; i < numFormats; ++i)
203 		if (isSupportedDepthStencilFormat(instanceInterface, device, pFormats[i]))
204 			return pFormats[i];
205 	return VK_FORMAT_UNDEFINED;
206 }
207 
208 enum Flags
209 {
210 	FLAG_TEST_DEPTH								= 1u << 0,
211 	FLAG_TEST_STENCIL							= 1u << 1,
212 	FLAG_DONT_USE_TEST_ATTACHMENT				= 1u << 2,
213 	FLAG_DONT_USE_EARLY_FRAGMENT_TESTS			= 1u << 3,
214 	FLAG_EARLY_AND_LATE_FRAGMENT_TESTS			= 1u << 4,
215 };
216 
217 class EarlyFragmentTest : public TestCase
218 {
219 public:
220 						EarlyFragmentTest	(tcu::TestContext&		testCtx,
221 											 const std::string		name,
222 											 const deUint32			flags);
223 
224 	void				initPrograms		(SourceCollections&		programCollection) const;
225 	TestInstance*		createInstance		(Context&				context) const;
226 	virtual void		checkSupport		(Context&				context) const;
227 
228 private:
229 	const deUint32		m_flags;
230 };
231 
EarlyFragmentTest(tcu::TestContext & testCtx,const std::string name,const deUint32 flags)232 EarlyFragmentTest::EarlyFragmentTest (tcu::TestContext& testCtx, const std::string name, const deUint32 flags)
233 	: TestCase	(testCtx, name)
234 	, m_flags	(flags)
235 {
236 }
237 
initPrograms(SourceCollections & programCollection) const238 void EarlyFragmentTest::initPrograms (SourceCollections& programCollection) const
239 {
240 	// Vertex
241 	{
242 		std::ostringstream src;
243 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
244 			<< "\n"
245 			<< "layout(location = 0) in highp vec4 position;\n"
246 			<< "\n"
247 			<< "out gl_PerVertex {\n"
248 			<< "   vec4 gl_Position;\n"
249 			<< "};\n"
250 			<< "\n"
251 			<< "void main (void)\n"
252 			<< "{\n"
253 			<< "    gl_Position = position;\n"
254 			<< "}\n";
255 
256 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
257 	}
258 
259 	// Fragment
260 	if ((m_flags & FLAG_EARLY_AND_LATE_FRAGMENT_TESTS) == 0)
261 	{
262 		const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0;
263 		std::ostringstream src;
264 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
265 			<< "\n"
266 			<< (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "")
267 			<< "layout(location = 0) out highp vec4 fragColor;\n"
268 			<< "\n"
269 			<< "layout(binding = 0) coherent buffer Output {\n"
270 			<< "    uint result;\n"
271 			<< "} sb_out;\n"
272 			<< "\n"
273 			<< "void main (void)\n"
274 			<< "{\n"
275 			<< "    atomicAdd(sb_out.result, 1u);\n"
276 			<< "	fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
277 			<< "}\n";
278 
279 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
280 	}
281 	else
282 	{
283 		const SpirVAsmBuildOptions	buildOptionsSpr	(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3);
284 		const std::string			src				=
285 			"; SPIR-V\n"
286 			"; Version: 1.0\n"
287 			"; Bound: 24\n"
288 			"; Schema: 0\n"
289 			"OpCapability Shader\n"
290 			"OpExtension \"SPV_AMD_shader_early_and_late_fragment_tests\"\n"
291 			"%1 = OpExtInstImport \"GLSL.std.450\"\n"
292 			"OpMemoryModel Logical GLSL450\n"
293 			"OpEntryPoint Fragment %4 \"main\" %20\n"
294 			"OpExecutionMode %4 OriginUpperLeft\n"
295 			"OpExecutionMode %4 EarlyAndLateFragmentTestsAMD\n"
296 			"OpMemberDecorate %7 0 Coherent\n"
297 			"OpMemberDecorate %7 0 Offset 0\n"
298 			"OpDecorate %7 BufferBlock\n"
299 			"OpDecorate %9 DescriptorSet 0\n"
300 			"OpDecorate %9 Binding 0\n"
301 			"OpDecorate %20 Location 0\n"
302 			"%2 = OpTypeVoid\n"
303 			"%3 = OpTypeFunction %2\n"
304 			"%6 = OpTypeInt 32 0\n"
305 			"%7 = OpTypeStruct %6\n"
306 			"%8 = OpTypePointer Uniform %7\n"
307 			"%9 = OpVariable %8 Uniform\n"
308 			"%10 = OpTypeInt 32 1\n"
309 			"%11 = OpConstant %10 0\n"
310 			"%12 = OpTypePointer Uniform %6\n"
311 			"%14 = OpConstant %6 1\n"
312 			"%15 = OpConstant %6 0\n"
313 			"%17 = OpTypeFloat 32\n"
314 			"%18 = OpTypeVector %17 4\n"
315 			"%19 = OpTypePointer Output %18\n"
316 			"%20 = OpVariable %19 Output\n"
317 			"%21 = OpConstant %17 1\n"
318 			"%22 = OpConstant %17 0\n"
319 			"%23 = OpConstantComposite %18 %21 %21 %22 %21\n"
320 			"%4 = OpFunction %2 None %3\n"
321 			"%5 = OpLabel\n"
322 			"%13 = OpAccessChain %12 %9 %11\n"
323 			"%16 = OpAtomicIAdd %6 %13 %14 %15 %14\n"
324 			"OpStore %20 %23\n"
325 			"OpReturn\n"
326 			"OpFunctionEnd\n";
327 		programCollection.spirvAsmSources.add("frag") << src << buildOptionsSpr;
328 	}
329 }
330 
331 class EarlyFragmentTestInstance : public TestInstance
332 {
333 public:
334 							EarlyFragmentTestInstance (Context& context, const deUint32 flags);
335 
336 	tcu::TestStatus			iterate					  (void);
337 
338 private:
339 	enum TestMode
340 	{
341 		MODE_INVALID,
342 		MODE_DEPTH,
343 		MODE_STENCIL,
344 	};
345 
346 	const TestMode			m_testMode;
347 	const bool				m_useTestAttachment;
348 	const bool				m_useEarlyTests;
349 	const bool				m_useEarlyLateTests;
350 };
351 
EarlyFragmentTestInstance(Context & context,const deUint32 flags)352 EarlyFragmentTestInstance::EarlyFragmentTestInstance (Context& context, const deUint32 flags)
353 	: TestInstance			(context)
354 	, m_testMode			(flags & FLAG_TEST_DEPTH   ? MODE_DEPTH :
355 							 flags & FLAG_TEST_STENCIL ? MODE_STENCIL : MODE_INVALID)
356 	, m_useTestAttachment	((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0)
357 	, m_useEarlyTests		((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0)
358 	, m_useEarlyLateTests	((flags & FLAG_EARLY_AND_LATE_FRAGMENT_TESTS) == FLAG_EARLY_AND_LATE_FRAGMENT_TESTS)
359 {
360 	DE_ASSERT(m_testMode != MODE_INVALID);
361 }
362 
iterate(void)363 tcu::TestStatus EarlyFragmentTestInstance::iterate (void)
364 {
365 	const DeviceInterface&		vk					= m_context.getDeviceInterface();
366 	const InstanceInterface&	vki					= m_context.getInstanceInterface();
367 	const VkDevice				device				= m_context.getDevice();
368 	const VkPhysicalDevice		physDevice			= m_context.getPhysicalDevice();
369 	const VkQueue				queue				= m_context.getUniversalQueue();
370 	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
371 	Allocator&					allocator			= m_context.getDefaultAllocator();
372 
373 	// Color attachment
374 
375 	const tcu::IVec2				renderSize			= tcu::IVec2(32, 32);
376 	const VkFormat					colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
377 	const VkImageSubresourceRange	colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
378 	const Unique<VkImage>			colorImage			(makeImage(vk, device, makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
379 	const UniquePtr<Allocation>		colorImageAlloc		(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
380 	const Unique<VkImageView>		colorImageView		(makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
381 
382 	// Test attachment (depth or stencil)
383 	static const VkFormat stencilFormats[] =
384 	{
385 		// One of the following formats must be supported, as per spec requirement.
386 		VK_FORMAT_S8_UINT,
387 		VK_FORMAT_D16_UNORM_S8_UINT,
388 		VK_FORMAT_D24_UNORM_S8_UINT,
389 		VK_FORMAT_D32_SFLOAT_S8_UINT,
390 	};
391 
392 	const VkFormat testFormat = (m_testMode == MODE_STENCIL ? pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats)
393 															: VK_FORMAT_D16_UNORM);		// spec requires this format to be supported
394 	if (testFormat == VK_FORMAT_UNDEFINED)
395 		return tcu::TestStatus::fail("Required depth/stencil format not supported");
396 
397 	if (m_useTestAttachment)
398 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format " << getFormatName(testFormat) << tcu::TestLog::EndMessage;
399 
400 	const VkImageSubresourceRange	testSubresourceRange	= makeImageSubresourceRange(getImageAspectFlags(testFormat), 0u, 1u, 0u, 1u);
401 	const Unique<VkImage>			testImage				(makeImage(vk, device, makeImageCreateInfo(renderSize, testFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)));
402 	const UniquePtr<Allocation>		testImageAlloc			(bindImage(vk, device, allocator, *testImage, MemoryRequirement::Any));
403 	const Unique<VkImageView>		testImageView			(makeImageView(vk, device, *testImage, VK_IMAGE_VIEW_TYPE_2D, testFormat, testSubresourceRange));
404 	const VkImageView				attachmentImages[]		= { *colorImageView, *testImageView };
405 	const deUint32					numUsedAttachmentImages = (m_useTestAttachment ? 2u : 1u);
406 
407 	// Vertex buffer
408 
409 	const deUint32					numVertices				= 6;
410 	const VkDeviceSize				vertexBufferSizeBytes	= sizeof(tcu::Vec4) * numVertices;
411 	const Unique<VkBuffer>			vertexBuffer			(makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
412 	const UniquePtr<Allocation>		vertexBufferAlloc		(bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
413 
414 	{
415 		tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
416 
417 		// A small +0.00001f adjustment for the z-coordinate to get the expected rounded value for depth.
418 		pVertices[0] = tcu::Vec4( 1.0f, -1.0f,  0.50001f,  1.0f);
419 		pVertices[1] = tcu::Vec4(-1.0f, -1.0f,  0.0f,      1.0f);
420 		pVertices[2] = tcu::Vec4(-1.0f,  1.0f,  0.50001f,  1.0f);
421 
422 		pVertices[3] = tcu::Vec4(-1.0f,  1.0f,  0.50001f,  1.0f);
423 		pVertices[4] = tcu::Vec4( 1.0f,  1.0f,  1.0f,      1.0f);
424 		pVertices[5] = tcu::Vec4( 1.0f, -1.0f,  0.50001f,  1.0f);
425 
426 		flushAlloc(vk, device, *vertexBufferAlloc);
427 		// No barrier needed, flushed memory is automatically visible
428 	}
429 
430 	// Result buffer
431 
432 	const VkDeviceSize				resultBufferSizeBytes	= sizeof(deUint32);
433 	const Unique<VkBuffer>			resultBuffer			(makeBuffer(vk, device, resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
434 	const UniquePtr<Allocation>		resultBufferAlloc		(bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));
435 
436 	{
437 		deUint32* const pData = static_cast<deUint32*>(resultBufferAlloc->getHostPtr());
438 
439 		*pData = 0;
440 		flushAlloc(vk, device, *resultBufferAlloc);
441 	}
442 
443 	// Render result buffer (to retrieve color attachment contents)
444 
445 	const VkDeviceSize				colorBufferSizeBytes	= tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
446 	const Unique<VkBuffer>			colorBuffer				(makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
447 	const UniquePtr<Allocation>		colorBufferAlloc		(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
448 
449 	// Descriptors
450 
451 	const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
452 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
453 		.build(vk, device));
454 
455 	const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
456 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
457 		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
458 
459 	const Unique<VkDescriptorSet> descriptorSet				 (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
460 	const VkDescriptorBufferInfo  resultBufferDescriptorInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
461 
462 	DescriptorSetUpdateBuilder()
463 		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo)
464 		.update(vk, device);
465 
466 	// Pipeline
467 
468 	const Unique<VkShaderModule>	vertexModule  (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
469 	const Unique<VkShaderModule>	fragmentModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
470 	const Unique<VkRenderPass>		renderPass	  (makeRenderPass(vk, device, colorFormat, m_useTestAttachment, testFormat));
471 	const Unique<VkFramebuffer>		framebuffer	  (makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages, renderSize.x(), renderSize.y()));
472 	const Unique<VkPipelineLayout>	pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
473 	const Unique<VkPipeline>		pipeline	  (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, renderSize,
474 												  (m_testMode == MODE_DEPTH), (m_testMode == MODE_STENCIL)));
475 	const Unique<VkCommandPool>		cmdPool		  (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
476 	const Unique<VkCommandBuffer>	cmdBuffer	  (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
477 
478 	// Draw commands
479 
480 	{
481 		const VkRect2D renderArea = {
482 			makeOffset2D(0, 0),
483 			makeExtent2D(renderSize.x(), renderSize.y()),
484 		};
485 		const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
486 		const VkDeviceSize vertexBufferOffset = 0ull;
487 
488 		beginCommandBuffer(vk, *cmdBuffer);
489 
490 		{
491 			const VkImageMemoryBarrier barriers[] = {
492 				makeImageMemoryBarrier(
493 					0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
494 					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
495 					*colorImage, colorSubresourceRange),
496 				makeImageMemoryBarrier(
497 					0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
498 					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
499 					*testImage, testSubresourceRange),
500 			};
501 
502 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
503 				0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
504 		}
505 
506 		// Will clear the attachments with specified depth and stencil values.
507 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor, 0.5f, 0u);
508 
509 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
510 		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
511 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
512 
513 		// Mask half of the attachment image with value that will pass the stencil test.
514 		if (m_useTestAttachment && m_testMode == MODE_STENCIL)
515 			commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0), makeExtent2D(renderSize.x()/2, renderSize.y()), 1u);
516 
517 		vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
518 		endRenderPass(vk, *cmdBuffer);
519 
520 		copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, renderSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
521 
522 		endCommandBuffer(vk, *cmdBuffer);
523 		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
524 	}
525 
526 	// Log result image
527 	{
528 		invalidateAlloc(vk, device, *colorBufferAlloc);
529 
530 		const tcu::ConstPixelBufferAccess	imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc->getHostPtr());
531 		tcu::TextureLevel					referenceImage(mapVkFormat(colorFormat), renderSize.x(), renderSize.y());
532 
533 		if (m_useTestAttachment == true)
534 		{
535 			const tcu::Vec4	fillColor	= tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f);
536 			const tcu::Vec4	clearColor	= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
537 
538 			tcu::clear(referenceImage.getAccess(), clearColor);
539 
540 			if (m_testMode == MODE_DEPTH)
541 			{
542 				int xOffset = 0;
543 
544 				for (int y = 0; y < renderSize.y() - 1; y++)
545 				{
546 					for (int x = 0; x < renderSize.x() - 1 - xOffset; x++)
547 					{
548 						referenceImage.getAccess().setPixel(fillColor, x, y);
549 					}
550 
551 					xOffset++;
552 				}
553 			}
554 
555 			if (m_testMode == MODE_STENCIL)
556 			{
557 				for (int y = 0; y < renderSize.y(); y++)
558 				{
559 					for (int x = 0; x < renderSize.x() / 2; x++)
560 					{
561 						referenceImage.getAccess().setPixel(fillColor, x, y);
562 					}
563 				}
564 			}
565 		}
566 		else
567 		{
568 			const tcu::Vec4	clearColor = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f);
569 
570 			tcu::clear(referenceImage.getAccess(), clearColor);
571 		}
572 
573 		if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", referenceImage.getAccess(), imagePixelAccess, tcu::Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
574 			return tcu::TestStatus::fail("Rendered color image is not correct");
575 	}
576 
577 	// Verify results
578 	{
579 		invalidateAlloc(vk, device, *resultBufferAlloc);
580 
581 		const int  actualCounter	   = *static_cast<deInt32*>(resultBufferAlloc->getHostPtr());
582 		const bool expectPartialResult = (m_useEarlyTests && m_useTestAttachment);
583 		const int  expectedCounter	   = expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y();
584 		const int  tolerance		   = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3	: 0;
585 		const int  expectedMin         = de::max(0, expectedCounter - tolerance);
586 		const int  expectedMax		   = (m_useEarlyLateTests ? (renderSize.x() * renderSize.y()) : (expectedCounter + tolerance));
587 
588 		tcu::TestLog& log = m_context.getTestContext().getLog();
589 		log << tcu::TestLog::Message << "Expected value"
590 			<< (expectPartialResult ? " in range: [" + de::toString(expectedMin) + ", " + de::toString(expectedMax) + "]" : ": " + de::toString(expectedCounter))
591 			<< tcu::TestLog::EndMessage;
592 		log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage;
593 
594 		if (expectedMin <= actualCounter && actualCounter <= expectedMax)
595 			return tcu::TestStatus::pass("Success");
596 		else
597 			return tcu::TestStatus::fail("Value out of range");
598 	}
599 }
600 
createInstance(Context & context) const601 TestInstance* EarlyFragmentTest::createInstance (Context& context) const
602 {
603 	return new EarlyFragmentTestInstance(context, m_flags);
604 }
605 
checkSupport(Context & context) const606 void EarlyFragmentTest::checkSupport (Context& context) const
607 {
608 	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
609 #ifndef CTS_USES_VULKANSC
610 	if ((m_flags & FLAG_EARLY_AND_LATE_FRAGMENT_TESTS) == FLAG_EARLY_AND_LATE_FRAGMENT_TESTS)
611 	{
612 		context.requireDeviceFunctionality("VK_AMD_shader_early_and_late_fragment_tests");
613 		if (context.getShaderEarlyAndLateFragmentTestsFeaturesAMD().shaderEarlyAndLateFragmentTests == VK_FALSE)
614 			TCU_THROW(NotSupportedError, "shaderEarlyAndLateFragmentTests is not supported");
615 	}
616 #endif
617 }
618 
619 class EarlyFragmentDiscardTestInstance : public EarlyFragmentTestInstance
620 {
621 public:
622 							EarlyFragmentDiscardTestInstance	(Context& context, const deUint32 flags);
623 
624 	tcu::TestStatus			iterate								(void);
625 
626 private:
627 	tcu::TextureLevel	generateReferenceColorImage				(const tcu::TextureFormat format, const tcu::IVec2& renderSize);
628 	enum TestMode
629 	{
630 		MODE_INVALID,
631 		MODE_DEPTH,
632 		MODE_STENCIL,
633 	};
634 
635 	const TestMode			m_testMode;
636 	const bool				m_useTestAttachment;
637 	const bool				m_useEarlyTests;
638 	const bool				m_useEarlyLateTests;
639 };
640 
EarlyFragmentDiscardTestInstance(Context & context,const deUint32 flags)641 EarlyFragmentDiscardTestInstance::EarlyFragmentDiscardTestInstance (Context& context, const deUint32 flags)
642 	: EarlyFragmentTestInstance			(context, flags)
643 	, m_testMode			(flags & FLAG_TEST_DEPTH   ? MODE_DEPTH :
644 							 flags & FLAG_TEST_STENCIL ? MODE_STENCIL : MODE_INVALID)
645 	, m_useTestAttachment	((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0)
646 	, m_useEarlyTests		((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0)
647 	, m_useEarlyLateTests	((flags& FLAG_EARLY_AND_LATE_FRAGMENT_TESTS) != 0)
648 {
649 	DE_ASSERT(m_testMode != MODE_INVALID);
650 }
651 
generateReferenceColorImage(const tcu::TextureFormat format,const tcu::IVec2 & renderSize)652 tcu::TextureLevel EarlyFragmentDiscardTestInstance::generateReferenceColorImage(const tcu::TextureFormat format, const tcu::IVec2 &renderSize)
653 {
654 	tcu::TextureLevel	image(format, renderSize.x(), renderSize.y());
655 	const tcu::Vec4		clearColor	= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
656 
657 	tcu::clear(image.getAccess(), clearColor);
658 
659 	return image;
660 }
661 
iterate(void)662 tcu::TestStatus EarlyFragmentDiscardTestInstance::iterate (void)
663 {
664 	const DeviceInterface&		vk					= m_context.getDeviceInterface();
665 	const InstanceInterface&	vki					= m_context.getInstanceInterface();
666 	const VkDevice				device				= m_context.getDevice();
667 	const VkPhysicalDevice		physDevice			= m_context.getPhysicalDevice();
668 	const VkQueue				queue				= m_context.getUniversalQueue();
669 	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
670 	Allocator&					allocator			= m_context.getDefaultAllocator();
671 
672 	DE_ASSERT(m_useTestAttachment);
673 
674 	// Color attachment
675 	const tcu::IVec2				renderSize				= tcu::IVec2(32, 32);
676 	const VkFormat					colorFormat				= VK_FORMAT_R8G8B8A8_UNORM;
677 	const VkImageSubresourceRange	colorSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
678 	const Unique<VkImage>			colorImage				(makeImage(vk, device, makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
679 	const UniquePtr<Allocation>		colorImageAlloc			(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
680 	const Unique<VkImageView>		colorImageView			(makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
681 
682 	// Test attachment (depth or stencil)
683 	static const VkFormat stencilFormats[] =
684 	{
685 		// One of the following formats must be supported, as per spec requirement.
686 		VK_FORMAT_S8_UINT,
687 		VK_FORMAT_D16_UNORM_S8_UINT,
688 		VK_FORMAT_D24_UNORM_S8_UINT,
689 		VK_FORMAT_D32_SFLOAT_S8_UINT,
690 	};
691 
692 	const VkFormat depthStencilFormat = (m_testMode == MODE_STENCIL ? pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats)
693 										 : VK_FORMAT_D16_UNORM);		// spec requires this format to be supported
694 
695 	if (depthStencilFormat == VK_FORMAT_UNDEFINED)
696 		return tcu::TestStatus::fail("Required depth/stencil format not supported");
697 
698 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format " << getFormatName(depthStencilFormat) << tcu::TestLog::EndMessage;
699 
700 	const VkImageSubresourceRange	testSubresourceRange	= makeImageSubresourceRange(getImageAspectFlags(depthStencilFormat), 0u, 1u, 0u, 1u);
701 	const Unique<VkImage>			testImage				(makeImage(vk, device, makeImageCreateInfo(renderSize, depthStencilFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
702 	const UniquePtr<Allocation>		testImageAlloc			(bindImage(vk, device, allocator, *testImage, MemoryRequirement::Any));
703 	const Unique<VkImageView>		testImageView			(makeImageView(vk, device, *testImage, VK_IMAGE_VIEW_TYPE_2D, depthStencilFormat, testSubresourceRange));
704 	const VkImageView				attachmentImages[]		= { *colorImageView, *testImageView };
705 	const deUint32					numUsedAttachmentImages = DE_LENGTH_OF_ARRAY(attachmentImages);
706 
707 	// Vertex buffer
708 
709 	const deUint32					numVertices				= 6;
710 	const VkDeviceSize				vertexBufferSizeBytes	= sizeof(tcu::Vec4) * numVertices;
711 	const Unique<VkBuffer>			vertexBuffer			(makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
712 	const UniquePtr<Allocation>		vertexBufferAlloc		(bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
713 
714 	{
715 		tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
716 
717 		pVertices[0] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
718 		pVertices[1] = tcu::Vec4(-1.0f, -1.0f,  0.0f,  1.0f);
719 		pVertices[2] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
720 
721 		pVertices[3] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
722 		pVertices[4] = tcu::Vec4( 1.0f,  1.0f,  1.0f,  1.0f);
723 		pVertices[5] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
724 
725 		flushAlloc(vk, device, *vertexBufferAlloc);
726 		// No barrier needed, flushed memory is automatically visible
727 	}
728 
729 	// Result buffer
730 
731 	const VkDeviceSize				resultBufferSizeBytes	= sizeof(deUint32);
732 	const Unique<VkBuffer>			resultBuffer			(makeBuffer(vk, device, resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
733 	const UniquePtr<Allocation>		resultBufferAlloc		(bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));
734 
735 	{
736 		deUint32* const pData = static_cast<deUint32*>(resultBufferAlloc->getHostPtr());
737 
738 		*pData = 0;
739 		flushAlloc(vk, device, *resultBufferAlloc);
740 	}
741 
742 	// Render result buffer (to retrieve color attachment contents)
743 
744 	const VkDeviceSize				colorBufferSizeBytes	= tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
745 	const Unique<VkBuffer>			colorBuffer				(makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
746 	const UniquePtr<Allocation>		colorBufferAlloc		(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
747 
748 	// Depth stencil result buffer (to retrieve depth-stencil attachment contents)
749 
750 	const VkDeviceSize				dsBufferSizeBytes	= tcu::getPixelSize(mapVkFormat(depthStencilFormat)) * renderSize.x() * renderSize.y();
751 	const Unique<VkBuffer>			dsBuffer			(makeBuffer(vk, device, dsBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
752 	const UniquePtr<Allocation>		dsBufferAlloc		(bindBuffer(vk, device, allocator, *dsBuffer, MemoryRequirement::HostVisible));
753 
754 	// Descriptors
755 
756 	const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
757 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
758 		.build(vk, device));
759 
760 	const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
761 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
762 		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
763 
764 	const Unique<VkDescriptorSet> descriptorSet				 (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
765 	const VkDescriptorBufferInfo  resultBufferDescriptorInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
766 
767 	DescriptorSetUpdateBuilder()
768 		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo)
769 		.update(vk, device);
770 
771 	// Pipeline
772 
773 	const Unique<VkShaderModule>	vertexModule  (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
774 	const Unique<VkShaderModule>	fragmentModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
775 	const Unique<VkRenderPass>		renderPass	  (makeRenderPass(vk, device, colorFormat, m_useTestAttachment, depthStencilFormat));
776 	const Unique<VkFramebuffer>		framebuffer	  (makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages, renderSize.x(), renderSize.y()));
777 	const Unique<VkPipelineLayout>	pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
778 	const Unique<VkPipeline>		pipeline	  (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, renderSize,
779 																		(m_testMode == MODE_DEPTH), (m_testMode == MODE_STENCIL),
780 																		VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_INCREMENT_AND_CLAMP));
781 	const Unique<VkCommandPool>		cmdPool		  (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
782 	const Unique<VkCommandBuffer>	cmdBuffer	  (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
783 
784 	// Draw commands
785 	{
786 		const VkRect2D renderArea = {
787 			makeOffset2D(0, 0),
788 			makeExtent2D(renderSize.x(), renderSize.y()),
789 		};
790 		const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
791 		const VkDeviceSize vertexBufferOffset = 0ull;
792 
793 		beginCommandBuffer(vk, *cmdBuffer);
794 
795 		{
796 			const VkImageMemoryBarrier barriers[] = {
797 				makeImageMemoryBarrier(
798 					0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
799 					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
800 					*colorImage, colorSubresourceRange),
801 				makeImageMemoryBarrier(
802 					0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
803 					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
804 					*testImage, testSubresourceRange),
805 			};
806 
807 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
808 				0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
809 		}
810 
811 		// Will clear the attachments with specified depth and stencil values.
812 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor, 0.5f, 3u);
813 
814 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
815 		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
816 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
817 
818 		// Mask half of the attachment image with value that will pass the stencil test.
819 		if (m_testMode == MODE_STENCIL)
820 			commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0), makeExtent2D(renderSize.x()/2, renderSize.y()), 1u);
821 
822 		vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
823 		endRenderPass(vk, *cmdBuffer);
824 
825 		copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, renderSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
826 		VkImageAspectFlags	dsAspect = m_testMode == MODE_DEPTH ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT;
827 		VkImageLayout		dsImageLayout = m_testMode == MODE_DEPTH ? VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
828 		copyImageToBuffer(vk, *cmdBuffer, *testImage, *dsBuffer, renderSize, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, dsImageLayout, 1u, dsAspect, dsAspect);
829 
830 		endCommandBuffer(vk, *cmdBuffer);
831 		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
832 	}
833 
834 	// Verify color output
835 	{
836 		invalidateAlloc(vk, device, *colorBufferAlloc);
837 
838 		const tcu::ConstPixelBufferAccess	imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc->getHostPtr());
839 		const tcu::TextureLevel				referenceImage	= generateReferenceColorImage(mapVkFormat(colorFormat), renderSize);
840 		if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", referenceImage.getAccess(), imagePixelAccess, tcu::Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
841 			printf("Rendered color image is not correct");
842 	}
843 
844 	// Verify depth-stencil output
845 	{
846 		invalidateAlloc(vk, device, *dsBufferAlloc);
847 		// the buffer holds only one aspect of d/s format
848 		tcu::TextureFormat format = vk::mapVkFormat(m_testMode == MODE_STENCIL ? VK_FORMAT_S8_UINT : depthStencilFormat);
849 		DE_ASSERT(format.order == tcu::TextureFormat::D || format.order == tcu::TextureFormat::S);
850 
851 		const tcu::ConstPixelBufferAccess	dsPixelAccess (format, renderSize.x(), renderSize.y(), 1, dsBufferAlloc->getHostPtr());
852 
853 		for(int z = 0; z < dsPixelAccess.getDepth(); z++)
854 		for(int y = 0; y < dsPixelAccess.getHeight(); y++)
855 		for(int x = 0; x < dsPixelAccess.getWidth(); x++)
856 		{
857 			float	depthValue		= (m_testMode == MODE_DEPTH) ? dsPixelAccess.getPixDepth(x, y, z) : 0.0f;
858 			int		stencilValue	= (m_testMode == MODE_STENCIL) ? dsPixelAccess.getPixStencil(x, y, z) : 0;
859 
860 			// Depth test should write to the depth buffer even when there is a discard in the fragment shader,
861 			// when early fragment tests are enabled. We allow some tolerance to account for precision error
862 			// on depth writes.
863 			if (m_testMode == MODE_DEPTH)
864 			{
865 				float tolerance = 0.0001f;
866 				if (m_useEarlyTests && ((x + y) < 31) && depthValue >= 0.50 + tolerance)
867 				{
868 					std::ostringstream error;
869 					error << "Rendered depth value [ "<< x << ", " << y << ", " << z << "] is not correct: " << depthValue << " >= 0.5f";
870 					TCU_FAIL(error.str().c_str());
871 				}
872 				// When early fragment tests are disabled, the depth test happens after the fragment shader, but as we are discarding
873 				// all fragments, the stored value in the depth buffer should be the clear one (0.5f).
874 				if (!m_useEarlyTests && deAbs(depthValue - 0.5f) > tolerance)
875 				{
876 					std::ostringstream error;
877 					error << "Rendered depth value [ "<< x << ", " << y << ", " << z << "] is not correct: " << depthValue << " != 0.5f";
878 					TCU_FAIL(error.str().c_str());
879 				}
880 			}
881 
882 			if (m_testMode == MODE_STENCIL)
883 			{
884 				if (m_useEarlyTests && ((x < 16 && stencilValue != 2u) || (x >= 16 && stencilValue != 4u)))
885 				{
886 					std::ostringstream error;
887 					error << "Rendered stencil value [ "<< x << ", " << y << ", " << z << "] is not correct: " << stencilValue << " != ";
888 					error << (x < 16 ? 2u : 4u);
889 					TCU_FAIL(error.str().c_str());
890 				}
891 
892 				if (!m_useEarlyTests && ((x < 16 && stencilValue != 1u) || (x >= 16 && stencilValue != 3u)))
893 				{
894 					std::ostringstream error;
895 					error << "Rendered stencil value [ "<< x << ", " << y << ", " << z << "] is not correct: " << stencilValue << " != ";
896 					error << (x < 16 ? 1u : 3u);
897 					TCU_FAIL(error.str().c_str());
898 				}
899 			}
900 		}
901 	}
902 
903 	// Verify we process all the fragments
904 	{
905 		invalidateAlloc(vk, device, *resultBufferAlloc);
906 
907 		const int  actualCounter	   = *static_cast<deInt32*>(resultBufferAlloc->getHostPtr());
908 		const bool expectPartialResult = m_useEarlyTests;
909 		const int  expectedCounter	   = expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y();
910 		const int  tolerance		   = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3	: 0;
911 		const int  expectedMin         = de::max(0, expectedCounter - tolerance);
912 		const int  expectedMax		   = (m_useEarlyLateTests ? (renderSize.x() * renderSize.y()) : (expectedCounter + tolerance));
913 
914 		tcu::TestLog& log = m_context.getTestContext().getLog();
915 		log << tcu::TestLog::Message << "Expected value"
916 			<< (expectPartialResult ? " in range: [" + de::toString(expectedMin) + ", " + de::toString(expectedMax) + "]" : ": " + de::toString(expectedCounter))
917 			<< tcu::TestLog::EndMessage;
918 		log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage;
919 
920 		if (expectedMin <= actualCounter && actualCounter <= expectedMax)
921 			return tcu::TestStatus::pass("Success");
922 		else
923 			return tcu::TestStatus::fail("Value out of range");
924 	}
925 }
926 
927 class EarlyFragmentDiscardTest : public EarlyFragmentTest
928 {
929 public:
930 						EarlyFragmentDiscardTest	(tcu::TestContext&		testCtx,
931 													 const std::string		name,
932 													 const deUint32			flags);
933 
934 	void				initPrograms				(SourceCollections&		programCollection) const;
935 	TestInstance*		createInstance				(Context&				context) const;
936 
937 private:
938 	const deUint32		m_flags;
939 };
940 
EarlyFragmentDiscardTest(tcu::TestContext & testCtx,const std::string name,const deUint32 flags)941 EarlyFragmentDiscardTest::EarlyFragmentDiscardTest (tcu::TestContext& testCtx, const std::string name, const deUint32 flags)
942 	: EarlyFragmentTest	(testCtx, name, flags)
943 	, m_flags (flags)
944 {
945 }
946 
createInstance(Context & context) const947 TestInstance* EarlyFragmentDiscardTest::createInstance (Context& context) const
948 {
949 	return new EarlyFragmentDiscardTestInstance(context, m_flags);
950 }
951 
initPrograms(SourceCollections & programCollection) const952 void EarlyFragmentDiscardTest::initPrograms(SourceCollections &programCollection) const
953 {
954 	// Vertex
955 	{
956 		std::ostringstream src;
957 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
958 			<< "\n"
959 			<< "layout(location = 0) in highp vec4 position;\n"
960 			<< "\n"
961 			<< "out gl_PerVertex {\n"
962 			<< "   vec4 gl_Position;\n"
963 			<< "};\n"
964 			<< "\n"
965 			<< "void main (void)\n"
966 			<< "{\n"
967 			<< "    gl_Position = position;\n"
968 			<< "}\n";
969 
970 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
971 	}
972 
973 	// Fragment
974 	{
975 		if ((m_flags & FLAG_EARLY_AND_LATE_FRAGMENT_TESTS) == 0)
976 		{
977 			const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0;
978 			std::ostringstream src;
979 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
980 				<< "\n"
981 				<< (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "")
982 				<< "layout(location = 0) out highp vec4 fragColor;\n"
983 				<< "\n"
984 				<< "layout(binding = 0) coherent buffer Output {\n"
985 				<< "    uint result;\n"
986 				<< "} sb_out;\n"
987 				<< "\n"
988 				<< "void main (void)\n"
989 				<< "{\n"
990 				<< "    atomicAdd(sb_out.result, 1u);\n"
991 				<< "    gl_FragDepth = 0.75f;\n"
992 				<< "    fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
993 				<< "    discard;\n"
994 				<< "}\n";
995 			programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
996 		}
997 		else
998 		{
999 			const SpirVAsmBuildOptions	buildOptionsSpr(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3);
1000 			const std::string			src =
1001 				"; SPIR - V\n"
1002 				"; Version: 1.0\n"
1003 				"; Generator: Khronos Glslang Reference Front End; 10\n"
1004 				"; Bound: 28\n"
1005 				"; Schema: 0\n"
1006 				"OpCapability Shader\n"
1007 				"OpExtension \"SPV_AMD_shader_early_and_late_fragment_tests\"\n"
1008 				"%1 = OpExtInstImport \"GLSL.std.450\"\n"
1009 				"OpMemoryModel Logical GLSL450\n"
1010 				"OpEntryPoint Fragment %4 \"main\" %19 %23\n"
1011 				"OpExecutionMode %4 OriginUpperLeft\n"
1012 				"OpExecutionMode %4 EarlyAndLateFragmentTestsAMD\n"
1013 				"OpExecutionMode %4 DepthReplacing\n"
1014 				"OpExecutionMode %4 DepthGreater\n"
1015 				"OpMemberDecorate %7 0 Coherent\n"
1016 				"OpMemberDecorate %7 0 Offset 0\n"
1017 				"OpDecorate %7 BufferBlock\n"
1018 				"OpDecorate %9 DescriptorSet 0\n"
1019 				"OpDecorate %9 Binding 0\n"
1020 				"OpDecorate %19 BuiltIn FragDepth\n"
1021 				"OpDecorate %23 Location 0\n"
1022 				"%2 = OpTypeVoid\n"
1023 				"%3 = OpTypeFunction %2\n"
1024 				"%6 = OpTypeInt 32 0\n"
1025 				"%7 = OpTypeStruct %6\n"
1026 				"%8 = OpTypePointer Uniform %7\n"
1027 				"%9 = OpVariable %8 Uniform\n"
1028 				"%10 = OpTypeInt 32 1\n"
1029 				"%11 = OpConstant %10 0\n"
1030 				"%12 = OpTypePointer Uniform %6\n"
1031 				"%14 = OpConstant %6 1\n"
1032 				"%15 = OpConstant %6 0\n"
1033 				"%17 = OpTypeFloat 32\n"
1034 				"%18 = OpTypePointer Output %17\n"
1035 				"%19 = OpVariable %18 Output\n"
1036 				"%20 = OpConstant %17 0.75\n"
1037 				"%21 = OpTypeVector %17 4\n"
1038 				"%22 = OpTypePointer Output %21\n"
1039 				"%23 = OpVariable %22 Output\n"
1040 				"%24 = OpConstant %17 1\n"
1041 				"%25 = OpConstant %17 0\n"
1042 				"%26 = OpConstantComposite %21 %24 %24 %25 %24\n"
1043 				"%4 = OpFunction %2 None %3\n"
1044 				"%5 = OpLabel\n"
1045 				"%13 = OpAccessChain %12 %9 %11\n"
1046 				"%16 = OpAtomicIAdd %6 %13 %14 %15 %14\n"
1047 				"OpStore %19 %20\n"
1048 				"OpStore %23 %26\n"
1049 				"OpKill\n"
1050 				"OpFunctionEnd\n";
1051 			programCollection.spirvAsmSources.add("frag") << src << buildOptionsSpr;
1052 		}
1053 	}
1054 }
1055 
1056 class EarlyFragmentSampleMaskTestInstance : public EarlyFragmentTestInstance
1057 {
1058 public:
1059 							EarlyFragmentSampleMaskTestInstance	(Context& context, const deUint32 flags, const deUint32 sampleCount);
1060 
1061 	tcu::TestStatus			iterate								(void);
1062 
1063 private:
1064 	tcu::TextureLevel	generateReferenceColorImage				(const tcu::TextureFormat format, const tcu::IVec2& renderSize);
1065 	Move<VkRenderPass>  makeRenderPass							(const DeviceInterface&				vk,
1066 																 const VkDevice						device,
1067 																 const VkFormat						colorFormat,
1068 																 const VkFormat						depthStencilFormat);
1069 	Move<VkPipeline>	makeGraphicsPipeline					(const DeviceInterface&	vk,
1070 																 const VkDevice			device,
1071 																 const VkPipelineLayout	pipelineLayout,
1072 																 const VkRenderPass		renderPass,
1073 																 const VkShaderModule		vertexModule,
1074 																 const VkShaderModule		fragmentModule,
1075 																 const tcu::IVec2&		renderSize,
1076 																 const bool				enableDepthTest,
1077 																 const bool				enableStencilTest,
1078 																 const VkStencilOp		stencilFailOp,
1079 																 const VkStencilOp		stencilPassOp);
1080 	enum TestMode
1081 	{
1082 		MODE_INVALID,
1083 		MODE_DEPTH,
1084 		MODE_STENCIL,
1085 	};
1086 
1087 	const TestMode			m_testMode;
1088 	const bool				m_useTestAttachment;
1089 	const bool				m_useEarlyTests;
1090 	const deUint32			m_sampleCount;
1091 };
1092 
EarlyFragmentSampleMaskTestInstance(Context & context,const deUint32 flags,const deUint32 sampleCount)1093 EarlyFragmentSampleMaskTestInstance::EarlyFragmentSampleMaskTestInstance (Context& context, const deUint32 flags, const deUint32 sampleCount)
1094 	: EarlyFragmentTestInstance			(context, flags)
1095 	, m_testMode			(flags & FLAG_TEST_DEPTH   ? MODE_DEPTH :
1096 							 flags & FLAG_TEST_STENCIL ? MODE_STENCIL : MODE_INVALID)
1097 	, m_useTestAttachment	((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0)
1098 	, m_useEarlyTests		((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0)
1099 	, m_sampleCount			(sampleCount)
1100 {
1101 	DE_ASSERT(m_testMode != MODE_INVALID);
1102 }
1103 
generateReferenceColorImage(const tcu::TextureFormat format,const tcu::IVec2 & renderSize)1104 tcu::TextureLevel EarlyFragmentSampleMaskTestInstance::generateReferenceColorImage(const tcu::TextureFormat format, const tcu::IVec2 &renderSize)
1105 {
1106 	tcu::TextureLevel	image(format, renderSize.x(), renderSize.y());
1107 	const tcu::Vec4		clearColor	= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1108 
1109 	tcu::clear(image.getAccess(), clearColor);
1110 
1111 	return image;
1112 }
1113 
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const tcu::IVec2 & renderSize,const bool enableDepthTest,const bool enableStencilTest,const VkStencilOp stencilFailOp,const VkStencilOp stencilPassOp)1114 Move<VkPipeline> EarlyFragmentSampleMaskTestInstance::makeGraphicsPipeline (const DeviceInterface&	vk,
1115 																			const VkDevice			device,
1116 																			const VkPipelineLayout	pipelineLayout,
1117 																			const VkRenderPass		renderPass,
1118 																			const VkShaderModule		vertexModule,
1119 																			const VkShaderModule		fragmentModule,
1120 																			const tcu::IVec2&		renderSize,
1121 																			const bool				enableDepthTest,
1122 																			const bool				enableStencilTest,
1123 																			const VkStencilOp		stencilFailOp,
1124 																			const VkStencilOp		stencilPassOp)
1125 {
1126 	const std::vector<VkViewport>			viewports					(1, makeViewport(renderSize));
1127 	const std::vector<VkRect2D>				scissors					(1, makeRect2D(renderSize));
1128 
1129 	const VkStencilOpState					stencilOpState				= makeStencilOpState(
1130 		stencilFailOp,			// stencil fail
1131 		stencilPassOp,			// depth & stencil pass
1132 		VK_STENCIL_OP_KEEP,		// depth only fail
1133 		VK_COMPARE_OP_EQUAL,	// compare op
1134 		0x3,					// compare mask
1135 		0xf,					// write mask
1136 		1u);					// reference
1137 
1138 	const VkPipelineDepthStencilStateCreateInfo	depthStencilStateCreateInfo	=
1139 	{
1140 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType                          sType
1141 		DE_NULL,													// const void*                              pNext
1142 		0u,															// VkPipelineDepthStencilStateCreateFlags   flags
1143 		enableDepthTest ? VK_TRUE : VK_FALSE,						// VkBool32                                 depthTestEnable
1144 		enableDepthTest ? VK_TRUE : VK_FALSE,						// VkBool32                                 depthWriteEnable
1145 		VK_COMPARE_OP_LESS,											// VkCompareOp                              depthCompareOp
1146 		VK_FALSE,													// VkBool32                                 depthBoundsTestEnable
1147 		enableStencilTest ? VK_TRUE : VK_FALSE,						// VkBool32                                 stencilTestEnable
1148 		stencilOpState,												// VkStencilOpState                         front
1149 		stencilOpState,												// VkStencilOpState                         back
1150 		0.0f,														// float                                    minDepthBounds
1151 		1.0f														// float                                    maxDepthBounds
1152 	};
1153 
1154 	// Only allow coverage on sample 0.
1155 	const VkSampleMask sampleMask = 0x1;
1156 
1157 	const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo =
1158 	{
1159 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType
1160 		DE_NULL,													// const void*								pNext
1161 		0u,															// VkPipelineMultisampleStateCreateFlags	flags
1162 		(VkSampleCountFlagBits)m_sampleCount,						// VkSampleCountFlagBits					rasterizationSamples
1163 		DE_TRUE,													// VkBool32									sampleShadingEnable
1164 		0.0f,														// float									minSampleShading
1165 		&sampleMask,												// const VkSampleMask*						pSampleMask
1166 		DE_FALSE,													// VkBool32									alphaToCoverageEnable
1167 		DE_FALSE,													// VkBool32									alphaToOneEnable
1168 	};
1169 
1170 	return vk::makeGraphicsPipeline(vk,										// const DeviceInterface&                        vk
1171 									device,									// const VkDevice                                device
1172 									pipelineLayout,							// const VkPipelineLayout                        pipelineLayout
1173 									vertexModule,							// const VkShaderModule                          vertexShaderModule
1174 									DE_NULL,								// const VkShaderModule                          tessellationControlModule
1175 									DE_NULL,								// const VkShaderModule                          tessellationEvalModule
1176 									DE_NULL,								// const VkShaderModule                          geometryShaderModule
1177 									fragmentModule,							// const VkShaderModule                          fragmentShaderModule
1178 									renderPass,								// const VkRenderPass                            renderPass
1179 									viewports,								// const std::vector<VkViewport>&                viewports
1180 									scissors,								// const std::vector<VkRect2D>&                  scissors
1181 									VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology                     topology
1182 									0u,										// const deUint32                                subpass
1183 									0u,										// const deUint32                                patchControlPoints
1184 									DE_NULL,								// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
1185 									DE_NULL,								// const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
1186 									&multisampleStateCreateInfo,			// const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
1187 									&depthStencilStateCreateInfo);			// const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
1188 }
1189 
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const VkFormat depthStencilFormat)1190 Move<VkRenderPass> EarlyFragmentSampleMaskTestInstance::makeRenderPass (const DeviceInterface&				vk,
1191 																		const VkDevice						device,
1192 																		const VkFormat						colorFormat,
1193 																		const VkFormat						depthStencilFormat)
1194 {
1195 	const bool								hasColor							= colorFormat != VK_FORMAT_UNDEFINED;
1196 	const bool								hasDepthStencil						= depthStencilFormat != VK_FORMAT_UNDEFINED;
1197 
1198 
1199 	const VkAttachmentDescription2			colorAttachmentDescription			=
1200 	{
1201 		VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,	// VkStructureType					sType;
1202 		DE_NULL,									// const void*						pNext;
1203 		(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags    flags
1204 		colorFormat,								// VkFormat                        format
1205 		(VkSampleCountFlagBits)m_sampleCount,		// VkSampleCountFlagBits           samples
1206 		VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp              loadOp
1207 		VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp             storeOp
1208 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp              stencilLoadOp
1209 		VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp             stencilStoreOp
1210 		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout                   initialLayout
1211 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout                   finalLayout
1212 	};
1213 
1214 	const VkAttachmentDescription2			depthStencilAttachmentDescription	=
1215 	{
1216 		VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,			// VkStructureType					sType;
1217 		DE_NULL,											// const void*						pNext;
1218 		(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags    flags
1219 		depthStencilFormat,									// VkFormat                        format
1220 		(VkSampleCountFlagBits)m_sampleCount,				// VkSampleCountFlagBits           samples
1221 		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp              loadOp
1222 		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp             storeOp
1223 		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp              stencilLoadOp
1224 		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp             stencilStoreOp
1225 		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout                   initialLayout
1226 		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL	// VkImageLayout                   finalLayout
1227 	};
1228 
1229 	const VkAttachmentDescription2			resolveAttachmentDescription			=
1230 	{
1231 		VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,	// VkStructureType					sType;
1232 		DE_NULL,									// const void*						pNext;
1233 		(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags    flags
1234 		colorFormat,								// VkFormat                        format
1235 		VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits           samples
1236 		VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp              loadOp
1237 		VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp             storeOp
1238 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp              stencilLoadOp
1239 		VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp             stencilStoreOp
1240 		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout                   initialLayout
1241 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout                   finalLayout
1242 	};
1243 
1244 		const VkAttachmentDescription2		resolveDepthStencilAttachmentDescription	=
1245 	{
1246 		VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,			// VkStructureType					sType;
1247 		DE_NULL,											// const void*						pNext;
1248 		(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags    flags
1249 		depthStencilFormat,									// VkFormat                        format
1250 		VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits           samples
1251 		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp              loadOp
1252 		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp             storeOp
1253 		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp              stencilLoadOp
1254 		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp             stencilStoreOp
1255 		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout                   initialLayout
1256 		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL	// VkImageLayout                   finalLayout
1257 	};
1258 
1259 	std::vector<VkAttachmentDescription2>	attachmentDescriptions;
1260 
1261 	if (hasColor)
1262 		attachmentDescriptions.push_back(colorAttachmentDescription);
1263 	if (hasDepthStencil)
1264 		attachmentDescriptions.push_back(depthStencilAttachmentDescription);
1265 	if (hasColor)
1266 		attachmentDescriptions.push_back(resolveAttachmentDescription);
1267 	if (hasDepthStencil)
1268 		attachmentDescriptions.push_back(resolveDepthStencilAttachmentDescription);
1269 
1270 	const VkAttachmentReference2				colorAttachmentRef					=
1271 	{
1272 		VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,			// VkStructureType		sType;
1273 		DE_NULL,											// const void*			pNext;
1274 		0u,													// deUint32				attachment
1275 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout		layout
1276 		VK_IMAGE_ASPECT_COLOR_BIT							// VkImageAspectFlags	aspectMask;
1277 	};
1278 
1279 	const VkAttachmentReference2				depthStencilAttachmentRef			=
1280 	{
1281 		VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,																// VkStructureType		sType;
1282 		DE_NULL,																								// const void*			pNext;
1283 		hasDepthStencil ? 1u : 0u,																				// deUint32				attachment
1284 		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,														// VkImageLayout		layout
1285 		VkImageAspectFlags(m_testMode == MODE_DEPTH ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT)	// VkImageAspectFlags	aspectMask;
1286 	};
1287 
1288 	const VkAttachmentReference2				resolveAttachmentRef					=
1289 	{
1290 		VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,			// VkStructureType		sType;
1291 		DE_NULL,											// const void*			pNext;
1292 		hasColor ? 2u : 0u,									// deUint32				attachment
1293 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout		layout
1294 		VK_IMAGE_ASPECT_COLOR_BIT							// VkImageAspectFlags	aspectMask;
1295 	};
1296 
1297 	const VkAttachmentReference2				depthStencilResolveAttachmentRef			=
1298 	{
1299 		VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,																// VkStructureType		sType;
1300 		DE_NULL,																								// const void*			pNext;
1301 		hasDepthStencil ? 3u : 0u,																				// deUint32				attachment
1302 		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,														// VkImageLayout		layout
1303 		VkImageAspectFlags(m_testMode == MODE_DEPTH ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT)	// VkImageAspectFlags	aspectMask;
1304 	};
1305 
1306 	// Using VK_RESOLVE_MODE_SAMPLE_ZERO_BIT as resolve mode, so no need to check its support as it is mandatory in the extension.
1307 	const VkSubpassDescriptionDepthStencilResolve depthStencilResolveDescription =
1308 	{
1309 		VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE,	// VkStructureType					sType;
1310 		DE_NULL,														// const void*						pNext;
1311 		VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,								// VkResolveModeFlagBits			depthResolveMode;
1312 		VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,								// VkResolveModeFlagBits			stencilResolveMode;
1313 		&depthStencilResolveAttachmentRef								// const VkAttachmentReference2*	pDepthStencilResolveAttachment;
1314 	};
1315 
1316 	const VkSubpassDescription2				subpassDescription					=
1317 	{
1318 		VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,						// VkStructureType					sType;
1319 		hasDepthStencil ? &depthStencilResolveDescription : DE_NULL,	// const void*						pNext;
1320 		(VkSubpassDescriptionFlags)0,									// VkSubpassDescriptionFlags		flags
1321 		VK_PIPELINE_BIND_POINT_GRAPHICS,								// VkPipelineBindPoint				pipelineBindPoint
1322 		0u,																// deUint32							viewMask;
1323 		0u,																// deUint32							inputAttachmentCount
1324 		DE_NULL,														// const VkAttachmentReference2*	pInputAttachments
1325 		hasColor ? 1u : 0u,												// deUint32							colorAttachmentCount
1326 		hasColor ? &colorAttachmentRef : DE_NULL,						// const VkAttachmentReference2*	pColorAttachments
1327 		hasColor ? &resolveAttachmentRef : DE_NULL,						// const VkAttachmentReference2*	pResolveAttachments
1328 		hasDepthStencil ? &depthStencilAttachmentRef : DE_NULL,			// const VkAttachmentReference2*	pDepthStencilAttachment
1329 		0u,																// deUint32							preserveAttachmentCount
1330 		DE_NULL															// const deUint32*					pPreserveAttachments
1331 	};
1332 
1333 	const VkRenderPassCreateInfo2			renderPassInfo						=
1334 	{
1335 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,								// VkStructureType                   sType
1336 		DE_NULL,																	// const void*                       pNext
1337 		(VkRenderPassCreateFlags)0,													// VkRenderPassCreateFlags           flags
1338 		(deUint32)attachmentDescriptions.size(),									// deUint32                          attachmentCount
1339 		attachmentDescriptions.size() > 0 ? &attachmentDescriptions[0] : DE_NULL,	// const VkAttachmentDescription2*    pAttachments
1340 		1u,																			// deUint32                          subpassCount
1341 		&subpassDescription,														// const VkSubpassDescription2*       pSubpasses
1342 		0u,																			// deUint32                          dependencyCount
1343 		DE_NULL,																	// const VkSubpassDependency*        pDependencies
1344 		0u,																			// deUint32						correlatedViewMaskCount;
1345 		DE_NULL,																	// const deUint32*					pCorrelatedViewMasks;
1346 	};
1347 
1348 	return createRenderPass2(vk, device, &renderPassInfo, DE_NULL);
1349 }
1350 
iterate(void)1351 tcu::TestStatus EarlyFragmentSampleMaskTestInstance::iterate (void)
1352 {
1353 	const DeviceInterface&		vk					= m_context.getDeviceInterface();
1354 	const InstanceInterface&	vki					= m_context.getInstanceInterface();
1355 	const VkDevice				device				= m_context.getDevice();
1356 	const VkPhysicalDevice		physDevice			= m_context.getPhysicalDevice();
1357 	const VkQueue				queue				= m_context.getUniversalQueue();
1358 	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1359 	Allocator&					allocator			= m_context.getDefaultAllocator();
1360 	const VkFormat				colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
1361 
1362 	DE_ASSERT(m_useTestAttachment);
1363 	DE_UNREF(m_useTestAttachment);
1364 
1365 	// Test attachment (depth or stencil)
1366 	static const VkFormat stencilFormats[] =
1367 	{
1368 		// One of the following formats must be supported, as per spec requirement.
1369 		VK_FORMAT_S8_UINT,
1370 		VK_FORMAT_D16_UNORM_S8_UINT,
1371 		VK_FORMAT_D24_UNORM_S8_UINT,
1372 		VK_FORMAT_D32_SFLOAT_S8_UINT,
1373 	};
1374 
1375 	const VkFormat depthStencilFormat = (m_testMode == MODE_STENCIL ? pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats)
1376 										 : VK_FORMAT_D16_UNORM);		// spec requires this format to be supported
1377 
1378 	if (depthStencilFormat == VK_FORMAT_UNDEFINED)
1379 		return tcu::TestStatus::fail("Required depth/stencil format not supported");
1380 
1381 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format " << getFormatName(depthStencilFormat) << tcu::TestLog::EndMessage;
1382 
1383 	// Check support for MSAA image formats used in the test.
1384 	VkImageFormatProperties formatProperties;
1385 	vki.getPhysicalDeviceImageFormatProperties(physDevice, colorFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u, &formatProperties);
1386 	if ((formatProperties.sampleCounts & m_sampleCount) == 0)
1387 		TCU_THROW(NotSupportedError, "Format does not support this number of samples for color format");
1388 
1389 	vki.getPhysicalDeviceImageFormatProperties(physDevice, depthStencilFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u, &formatProperties);
1390 	if ((formatProperties.sampleCounts & m_sampleCount) == 0)
1391 		TCU_THROW(NotSupportedError, "Format does not support this number of samples for depth-stencil format");
1392 
1393 	// Color attachment
1394 	const tcu::IVec2				renderSize				= tcu::IVec2(32, 32);
1395 	const VkImageSubresourceRange	colorSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1396 
1397 	const VkImageCreateInfo imageParams =
1398 	{
1399 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
1400 		DE_NULL,																	// const void*				pNext;
1401 		(VkImageCreateFlags)0,														// VkImageCreateFlags		flags;
1402 		VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
1403 		colorFormat,																// VkFormat					format;
1404 		makeExtent3D(renderSize.x(), renderSize.y(), 1),							// VkExtent3D				extent;
1405 		1u,																			// deUint32					mipLevels;
1406 		1u,																			// deUint32					arrayLayers;
1407 		(VkSampleCountFlagBits)m_sampleCount,										// VkSampleCountFlagBits	samples;
1408 		VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
1409 		VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
1410 		VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
1411 		0u,																			// deUint32					queueFamilyIndexCount;
1412 		DE_NULL,																	// const deUint32*			pQueueFamilyIndices;
1413 		VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout			initialLayout;
1414 	};
1415 	const Unique<VkImage>			colorImage				(makeImage(vk, device, imageParams));
1416 	const UniquePtr<Allocation>		colorImageAlloc			(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1417 	const Unique<VkImageView>		colorImageView			(makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
1418 
1419 	const Unique<VkImage>			resolveColorImage		(makeImage(vk, device, makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
1420 	const UniquePtr<Allocation>		resolveColorImageAlloc	(bindImage(vk, device, allocator, *resolveColorImage, MemoryRequirement::Any));
1421 	const Unique<VkImageView>		resolveColorImageView	(makeImageView(vk, device, *resolveColorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
1422 
1423 	// Depth-Stencil attachment
1424 	const VkImageSubresourceRange	depthStencilSubresourceRange	= makeImageSubresourceRange(getImageAspectFlags(depthStencilFormat), 0u, 1u, 0u, 1u);
1425 
1426 	const VkImageCreateInfo depthStencilImageParams =
1427 	{
1428 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,												// VkStructureType			sType;
1429 		DE_NULL,																			// const void*				pNext;
1430 		(VkImageCreateFlags)0,																// VkImageCreateFlags		flags;
1431 		VK_IMAGE_TYPE_2D,																	// VkImageType				imageType;
1432 		depthStencilFormat,																			// VkFormat					format;
1433 		makeExtent3D(renderSize.x(), renderSize.y(), 1),									// VkExtent3D				extent;
1434 		1u,																					// deUint32					mipLevels;
1435 		1u,																					// deUint32					arrayLayers;
1436 		(VkSampleCountFlagBits)m_sampleCount,												// VkSampleCountFlagBits	samples;
1437 		VK_IMAGE_TILING_OPTIMAL,															// VkImageTiling			tiling;
1438 		VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
1439 		VK_SHARING_MODE_EXCLUSIVE,															// VkSharingMode			sharingMode;
1440 		0u,																					// deUint32					queueFamilyIndexCount;
1441 		DE_NULL,																			// const deUint32*			pQueueFamilyIndices;
1442 		VK_IMAGE_LAYOUT_UNDEFINED,															// VkImageLayout			initialLayout;
1443 	};
1444 	const Unique<VkImage>			depthStencilImage				(makeImage(vk, device, depthStencilImageParams));
1445 	const UniquePtr<Allocation>		depthStencilImageAlloc			(bindImage(vk, device, allocator, *depthStencilImage, MemoryRequirement::Any));
1446 	const Unique<VkImageView>		depthStencilImageView			(makeImageView(vk, device, *depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, depthStencilFormat, depthStencilSubresourceRange));
1447 
1448 	const Unique<VkImage>			resolveDepthStencilImage				(makeImage(vk, device, makeImageCreateInfo(renderSize, depthStencilFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
1449 	const UniquePtr<Allocation>		resolveDepthStencilImageAlloc			(bindImage(vk, device, allocator, *resolveDepthStencilImage, MemoryRequirement::Any));
1450 	const Unique<VkImageView>		resolveDepthStencilImageView			(makeImageView(vk, device, *resolveDepthStencilImage, VK_IMAGE_VIEW_TYPE_2D, depthStencilFormat, depthStencilSubresourceRange));
1451 
1452 	const VkImageView				attachmentImages[]		= { *colorImageView, *depthStencilImageView, *resolveColorImageView, *resolveDepthStencilImageView };
1453 	const deUint32					numUsedAttachmentImages = DE_LENGTH_OF_ARRAY(attachmentImages);
1454 
1455 	// Vertex buffer
1456 
1457 	const deUint32					numVertices				= 6u;
1458 	const VkDeviceSize				vertexBufferSizeBytes	= sizeof(tcu::Vec4) * numVertices;
1459 	const Unique<VkBuffer>			vertexBuffer			(makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
1460 	const UniquePtr<Allocation>		vertexBufferAlloc		(bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
1461 
1462 	{
1463 		tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
1464 
1465 		pVertices[0] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
1466 		pVertices[1] = tcu::Vec4(-1.0f, -1.0f,  0.0f,  1.0f);
1467 		pVertices[2] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
1468 
1469 		pVertices[3] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
1470 		pVertices[4] = tcu::Vec4( 1.0f,  1.0f,  1.0f,  1.0f);
1471 		pVertices[5] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
1472 
1473 		flushAlloc(vk, device, *vertexBufferAlloc);
1474 		// No barrier needed, flushed memory is automatically visible
1475 	}
1476 
1477 	// Result buffer
1478 
1479 	const VkDeviceSize				resultBufferSizeBytes	= sizeof(deUint32);
1480 	const Unique<VkBuffer>			resultBuffer			(makeBuffer(vk, device, resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
1481 	const UniquePtr<Allocation>		resultBufferAlloc		(bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));
1482 
1483 	{
1484 		deUint32* const pData = static_cast<deUint32*>(resultBufferAlloc->getHostPtr());
1485 
1486 		*pData = 0;
1487 		flushAlloc(vk, device, *resultBufferAlloc);
1488 	}
1489 
1490 	// Render result buffer (to retrieve color attachment contents)
1491 
1492 	const VkDeviceSize				colorBufferSizeBytes	= tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
1493 	const Unique<VkBuffer>			colorBuffer				(makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1494 	const UniquePtr<Allocation>		colorBufferAlloc		(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1495 
1496 	// Depth stencil result buffer (to retrieve depth-stencil attachment contents)
1497 
1498 	const VkDeviceSize				dsBufferSizeBytes	= tcu::getPixelSize(mapVkFormat(depthStencilFormat)) * renderSize.x() * renderSize.y();
1499 	const Unique<VkBuffer>			dsBuffer			(makeBuffer(vk, device, dsBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1500 	const UniquePtr<Allocation>		dsBufferAlloc		(bindBuffer(vk, device, allocator, *dsBuffer, MemoryRequirement::HostVisible));
1501 
1502 	// Descriptors
1503 
1504 	const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
1505 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
1506 		.build(vk, device));
1507 
1508 	const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
1509 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1510 		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1511 
1512 	const Unique<VkDescriptorSet> descriptorSet				 (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1513 	const VkDescriptorBufferInfo  resultBufferDescriptorInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
1514 
1515 	DescriptorSetUpdateBuilder()
1516 		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo)
1517 		.update(vk, device);
1518 
1519 	// Pipeline
1520 
1521 	const Unique<VkShaderModule>	vertexModule  (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1522 	const Unique<VkShaderModule>	fragmentModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
1523 
1524 	const Unique<VkRenderPass>		renderPass	  (makeRenderPass(vk, device, colorFormat, depthStencilFormat));
1525 	const Unique<VkFramebuffer>		framebuffer	  (makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages, renderSize.x(), renderSize.y()));
1526 	const Unique<VkPipelineLayout>	pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
1527 	const Unique<VkPipeline>		pipeline	  (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, renderSize,
1528 																		(m_testMode == MODE_DEPTH), (m_testMode == MODE_STENCIL),
1529 																		VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_INCREMENT_AND_CLAMP));
1530 	const Unique<VkCommandPool>		cmdPool		  (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1531 	const Unique<VkCommandBuffer>	cmdBuffer	  (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1532 
1533 	// Draw commands
1534 
1535 	{
1536 		const VkRect2D renderArea = {
1537 			makeOffset2D(0, 0),
1538 			makeExtent2D(renderSize.x(), renderSize.y()),
1539 		};
1540 		const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1541 		const VkDeviceSize vertexBufferOffset = 0ull;
1542 
1543 		beginCommandBuffer(vk, *cmdBuffer);
1544 
1545 		{
1546 			const VkImageMemoryBarrier barriers[] = {
1547 				makeImageMemoryBarrier(
1548 					0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1549 					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1550 					*colorImage, colorSubresourceRange),
1551 				makeImageMemoryBarrier(
1552 					0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
1553 					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1554 					*depthStencilImage, depthStencilSubresourceRange),
1555 				makeImageMemoryBarrier(
1556 					0u,  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1557 					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1558 					*resolveColorImage, colorSubresourceRange),
1559 				makeImageMemoryBarrier(
1560 					0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
1561 					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1562 					*resolveDepthStencilImage, depthStencilSubresourceRange),
1563 			};
1564 
1565 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
1566 				0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1567 		}
1568 
1569 		// Will clear the attachments with specified depth and stencil values.
1570 		{
1571 			const VkClearValue			clearValues[]		=
1572 				{
1573 					makeClearValueColor(clearColor),						// attachment 0
1574 					makeClearValueDepthStencil(0.5f, 3u),					// attachment 1
1575 					makeClearValueColor(clearColor),						// attachment 2
1576 					makeClearValueDepthStencil(0.5f, 3u),					// attachment 3
1577 				};
1578 
1579 			const VkRenderPassBeginInfo	renderPassBeginInfo	=
1580 				{
1581 					VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,	// VkStructureType         sType;
1582 					DE_NULL,									// const void*             pNext;
1583 					*renderPass,								// VkRenderPass            renderPass;
1584 					*framebuffer,								// VkFramebuffer           framebuffer;
1585 					renderArea,									// VkRect2D                renderArea;
1586 					DE_LENGTH_OF_ARRAY(clearValues),			// deUint32                clearValueCount;
1587 					clearValues,								// const VkClearValue*     pClearValues;
1588 				};
1589 
1590 			vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1591 		}
1592 
1593 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1594 		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1595 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1596 
1597 		// Mask half of the attachment image with value that will pass the stencil test.
1598 		if (m_testMode == MODE_STENCIL)
1599 			commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0), makeExtent2D(renderSize.x()/2, renderSize.y()), 1u);
1600 
1601 		vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
1602 		endRenderPass(vk, *cmdBuffer);
1603 
1604 		copyImageToBuffer(vk, *cmdBuffer, *resolveColorImage, *colorBuffer, renderSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
1605 		VkImageAspectFlags dsAspect = m_testMode == MODE_DEPTH ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT;
1606 		copyImageToBuffer(vk, *cmdBuffer, *resolveDepthStencilImage, *dsBuffer, renderSize, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 1u, dsAspect, dsAspect);
1607 
1608 		endCommandBuffer(vk, *cmdBuffer);
1609 		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1610 	}
1611 
1612 	// Verify color output
1613 	{
1614 		invalidateAlloc(vk, device, *colorBufferAlloc);
1615 
1616 		const tcu::ConstPixelBufferAccess	imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc->getHostPtr());
1617 		const tcu::TextureLevel				referenceImage	= generateReferenceColorImage(mapVkFormat(colorFormat), renderSize);
1618 		if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", referenceImage.getAccess(), imagePixelAccess, tcu::Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
1619 			printf("Rendered color image is not correct");
1620 	}
1621 
1622 	// Verify depth-stencil output
1623 	{
1624 		invalidateAlloc(vk, device, *dsBufferAlloc);
1625 		tcu::TextureFormat format = mapVkFormat(depthStencilFormat);
1626 		const tcu::ConstPixelBufferAccess	dsPixelAccess (format, renderSize.x(), renderSize.y(), 1, dsBufferAlloc->getHostPtr());
1627 
1628 		for(int z = 0; z < dsPixelAccess.getDepth(); z++)
1629 		for(int y = 0; y < dsPixelAccess.getHeight(); y++)
1630 		for(int x = 0; x < dsPixelAccess.getWidth(); x++)
1631 		{
1632 			float	depthValue		= (m_testMode == MODE_DEPTH) ? dsPixelAccess.getPixDepth(x, y, z) : 0.0f;
1633 			int		stencilValue	= (m_testMode == MODE_STENCIL) ? dsPixelAccess.getPixStencil(x, y, z) : 0;
1634 
1635 			// Depth test should write to the depth buffer even when there is a discard in the fragment shader,
1636 			// when early fragment tests are enabled.
1637 			if (m_testMode == MODE_DEPTH)
1638 			{
1639 				if (m_useEarlyTests && ((x + y) < 31) && depthValue >= 0.5f)
1640 				{
1641 					std::ostringstream error;
1642 					error << "Rendered depth value [ "<< x << ", " << y << ", " << z << "] is not correct: " << depthValue << " >= 0.5f";
1643 					TCU_FAIL(error.str().c_str());
1644 				}
1645 				// When early fragment tests are disabled, the depth test happens after the fragment shader, but as we are discarding
1646 				// all fragments, the stored value in the depth buffer should be the clear one (0.5f).
1647 				if (!m_useEarlyTests && deAbs(depthValue - 0.5f) > 0.01f)
1648 				{
1649 					std::ostringstream error;
1650 					error << "Rendered depth value [ "<< x << ", " << y << ", " << z << "] is not correct: " << depthValue << " != 0.5f";
1651 					TCU_FAIL(error.str().c_str());
1652 				}
1653 			}
1654 
1655 			if (m_testMode == MODE_STENCIL)
1656 			{
1657 				if (m_useEarlyTests && ((x < 16 && stencilValue != 2u) || (x >= 16 && stencilValue != 4u)))
1658 				{
1659 					std::ostringstream error;
1660 					error << "Rendered stencil value [ "<< x << ", " << y << ", " << z << "] is not correct: " << stencilValue << " != ";
1661 					error << (x < 16 ? 2u : 4u);
1662 					TCU_FAIL(error.str().c_str());
1663 				}
1664 
1665 				if (!m_useEarlyTests && ((x < 16 && stencilValue != 1u) || (x >= 16 && stencilValue != 3u)))
1666 				{
1667 					std::ostringstream error;
1668 					error << "Rendered stencil value [ "<< x << ", " << y << ", " << z << "] is not correct: " << stencilValue << " != ";
1669 					error << (x < 16 ? 1u : 3u);
1670 					TCU_FAIL(error.str().c_str());
1671 				}
1672 			}
1673 		}
1674 	}
1675 
1676 	// Verify we process all the fragments
1677 	{
1678 		invalidateAlloc(vk, device, *resultBufferAlloc);
1679 
1680 		const int  actualCounter	   = *static_cast<deInt32*>(resultBufferAlloc->getHostPtr());
1681 		const bool expectPartialResult = m_useEarlyTests;
1682 		const int  expectedCounter	   = expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y();
1683 		const int  tolerance		   = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3	: 0;
1684 		const int  expectedMin         = de::max(0, expectedCounter - tolerance);
1685 
1686 		tcu::TestLog& log = m_context.getTestContext().getLog();
1687 		log << tcu::TestLog::Message << "Minimum expected value: " + de::toString(expectedMin) << tcu::TestLog::EndMessage;
1688 		log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage;
1689 
1690 		if (expectedMin <= actualCounter)
1691 			return tcu::TestStatus::pass("Success");
1692 		else
1693 			return tcu::TestStatus::fail("Value out of range");
1694 	}
1695 }
1696 
1697 class EarlyFragmentSampleMaskTest : public EarlyFragmentTest
1698 {
1699 public:
1700 						EarlyFragmentSampleMaskTest	(tcu::TestContext&		testCtx,
1701 													 const std::string		name,
1702 													 const deUint32			flags,
1703 													 const deUint32			sampleCount);
1704 
1705 	void				initPrograms				(SourceCollections&		programCollection) const override;
1706 	TestInstance*		createInstance				(Context&				context) const override;
1707 	void				checkSupport				(Context&				context) const override;
1708 
1709 private:
1710 	const deUint32		m_flags;
1711 	const deUint32		m_sampleCount;
1712 };
1713 
EarlyFragmentSampleMaskTest(tcu::TestContext & testCtx,const std::string name,const deUint32 flags,const deUint32 sampleCount)1714 EarlyFragmentSampleMaskTest::EarlyFragmentSampleMaskTest (tcu::TestContext& testCtx, const std::string name, const deUint32 flags, const deUint32 sampleCount)
1715 	: EarlyFragmentTest	(testCtx, name, flags)
1716 	, m_flags (flags)
1717 	, m_sampleCount (sampleCount)
1718 {
1719 }
1720 
createInstance(Context & context) const1721 TestInstance* EarlyFragmentSampleMaskTest::createInstance (Context& context) const
1722 {
1723 	return new EarlyFragmentSampleMaskTestInstance(context, m_flags, m_sampleCount);
1724 }
1725 
initPrograms(SourceCollections & programCollection) const1726 void EarlyFragmentSampleMaskTest::initPrograms(SourceCollections &programCollection) const
1727 {
1728 	// Vertex
1729 	{
1730 		std::ostringstream src;
1731 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1732 			<< "\n"
1733 			<< "layout(location = 0) in highp vec4 position;\n"
1734 			<< "\n"
1735 			<< "out gl_PerVertex {\n"
1736 			<< "   vec4 gl_Position;\n"
1737 			<< "};\n"
1738 			<< "\n"
1739 			<< "void main (void)\n"
1740 			<< "{\n"
1741 			<< "    gl_Position = position;\n"
1742 			<< "}\n";
1743 
1744 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1745 	}
1746 
1747 	// Fragment
1748 	{
1749 		if ((m_flags & FLAG_EARLY_AND_LATE_FRAGMENT_TESTS) == 0)
1750 		{
1751 			const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0;
1752 			std::ostringstream src;
1753 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1754 				<< "\n"
1755 				<< (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "")
1756 				<< "layout(location = 0) out highp vec4 fragColor;\n"
1757 				<< "\n"
1758 				<< "layout(binding = 0) coherent buffer Output {\n"
1759 				<< "    uint result;\n"
1760 				<< "} sb_out;\n"
1761 				<< "\n"
1762 				<< "void main (void)\n"
1763 				<< "{\n"
1764 				<< "    atomicAdd(sb_out.result, 1u);\n"
1765 				<< "    gl_SampleMask[0] = 0x0;\n"
1766 				<< "    fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
1767 				<< "    discard;\n"
1768 				<< "}\n";
1769 
1770 			programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1771 		}
1772 		else
1773 		{
1774 			const SpirVAsmBuildOptions	buildOptionsSpr(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3);
1775 			const std::string			option	= (((m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) != 0)					?
1776 													"OpExecutionMode %4 DepthReplacing\nOpExecutionMode %4 DepthGreater\n"	:
1777 													"");
1778 			const std::string			src		=
1779 				"; SPIR - V\n"
1780 				"; Version: 1.0\n"
1781 				"; Generator: Khronos Glslang Reference Front End; 10\n"
1782 				"; Bound: 30\n"
1783 				"; Schema: 0\n"
1784 				"OpCapability Shader\n"
1785 				"OpExtension \"SPV_AMD_shader_early_and_late_fragment_tests\"\n"
1786 				"%1 = OpExtInstImport \"GLSL.std.450\"\n"
1787 				"OpMemoryModel Logical GLSL450\n"
1788 				"OpEntryPoint Fragment %4 \"main\" %19 %25\n"
1789 				"OpExecutionMode %4 OriginUpperLeft\n"
1790 				"OpExecutionMode %4 EarlyAndLateFragmentTestsAMD\n"
1791 				+ option +
1792 				"OpMemberDecorate %7 0 Coherent\n"
1793 				"OpMemberDecorate %7 0 Offset 0\n"
1794 				"OpDecorate %7 BufferBlock\n"
1795 				"OpDecorate %9 DescriptorSet 0\n"
1796 				"OpDecorate %9 Binding 0\n"
1797 				"OpDecorate %19 BuiltIn SampleMask\n"
1798 				"OpDecorate %25 Location 0\n"
1799 				"%2 = OpTypeVoid\n"
1800 				"%3 = OpTypeFunction %2\n"
1801 				"%6 = OpTypeInt 32 0\n"
1802 				"%7 = OpTypeStruct %6\n"
1803 				"%8 = OpTypePointer Uniform %7\n"
1804 				"%9 = OpVariable %8 Uniform\n"
1805 				"%10 = OpTypeInt 32 1\n"
1806 				"%11 = OpConstant %10 0\n"
1807 				"%12 = OpTypePointer Uniform %6\n"
1808 				"%14 = OpConstant %6 1\n"
1809 				"%15 = OpConstant %6 0\n"
1810 				"%17 = OpTypeArray %10 %14\n"
1811 				"%18 = OpTypePointer Output %17\n"
1812 				"%19 = OpVariable %18 Output\n"
1813 				"%20 = OpTypePointer Output %10\n"
1814 				"%22 = OpTypeFloat 32\n"
1815 				"%23 = OpTypeVector %22 4\n"
1816 				"%24 = OpTypePointer Output %23\n"
1817 				"%25 = OpVariable %24 Output\n"
1818 				"%26 = OpConstant %22 1\n"
1819 				"%27 = OpConstant %22 0\n"
1820 				"%28 = OpConstantComposite %23 %26 %26 %27 %26\n"
1821 				"%4 = OpFunction %2 None %3\n"
1822 				"%5 = OpLabel\n"
1823 				"%13 = OpAccessChain %12 %9 %11\n"
1824 				"%16 = OpAtomicIAdd %6 %13 %14 %15 %14\n"
1825 				"%21 = OpAccessChain %20 %19 %11\n"
1826 				"OpStore %21 %11\n"
1827 				"OpStore %25 %28\n"
1828 				"OpKill\n"
1829 				"OpFunctionEnd\n";
1830 			programCollection.spirvAsmSources.add("frag") << src << buildOptionsSpr;
1831 		}
1832 	}
1833 }
1834 
checkSupport(Context & context) const1835 void EarlyFragmentSampleMaskTest::checkSupport(Context& context) const
1836 {
1837 	EarlyFragmentTest::checkSupport(context);
1838 
1839 	context.requireDeviceFunctionality("VK_KHR_depth_stencil_resolve");
1840 }
1841 
1842 struct SampleCountTestParams
1843 {
1844 	deUint32	sampleCount;
1845 	bool		earlyAndLate;
1846 	bool		alphaToCoverage;
1847 	bool		useMaintenance5;
1848 };
1849 
1850 class EarlyFragmentSampleCountTestInstance : public EarlyFragmentTestInstance
1851 {
1852 public:
1853 						EarlyFragmentSampleCountTestInstance	(Context& context, const SampleCountTestParams& testParams);
1854 
1855 	tcu::TestStatus		iterate									(void);
1856 
1857 private:
1858 	tcu::TextureLevel	generateReferenceColorImage				(const tcu::TextureFormat format, const tcu::IVec2& renderSize);
1859 
1860 	Move<VkRenderPass>	makeRenderPass							(const DeviceInterface&		vk,
1861 																 const VkDevice				device,
1862 																 const VkFormat				colorFormat,
1863 																 const VkFormat				depthStencilFormat);
1864 
1865 	Move<VkPipeline>	makeGraphicsPipeline					(const DeviceInterface&		vk,
1866 																 const VkDevice				device,
1867 																 const VkPipelineLayout		pipelineLayout,
1868 																 const VkRenderPass			renderPass,
1869 																 const VkShaderModule		vertexModule,
1870 																 const VkShaderModule		fragmentModule,
1871 																 const tcu::IVec2&			renderSize,
1872 																 const VkSampleMask			sampleMask);
1873 
1874 	const SampleCountTestParams		m_testParams;
1875 };
1876 
EarlyFragmentSampleCountTestInstance(Context & context,const SampleCountTestParams & testParams)1877 EarlyFragmentSampleCountTestInstance::EarlyFragmentSampleCountTestInstance (Context& context, const SampleCountTestParams& testParams)
1878 	: EarlyFragmentTestInstance	(context, FLAG_TEST_DEPTH)
1879 	, m_testParams				(testParams)
1880 {
1881 }
1882 
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const tcu::IVec2 & renderSize,const VkSampleMask sampleMask)1883 Move<VkPipeline> EarlyFragmentSampleCountTestInstance::makeGraphicsPipeline	(const DeviceInterface&	vk,
1884 																			const VkDevice			device,
1885 																			const VkPipelineLayout	pipelineLayout,
1886 																			const VkRenderPass		renderPass,
1887 																			const VkShaderModule	vertexModule,
1888 																			const VkShaderModule	fragmentModule,
1889 																			const tcu::IVec2&		renderSize,
1890 																			const VkSampleMask		sampleMask)
1891 {
1892 	const std::vector<VkViewport>				viewports					(1, makeViewport(renderSize));
1893 	const std::vector<VkRect2D>					scissors					(1, makeRect2D(renderSize));
1894 
1895 	const VkPipelineDepthStencilStateCreateInfo	depthStencilStateCreateInfo	=
1896 	{
1897 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType
1898 		DE_NULL,													// const void*								pNext
1899 		0u,															// VkPipelineDepthStencilStateCreateFlags	flags
1900 		VK_TRUE,													// VkBool32									depthTestEnable
1901 		VK_TRUE,													// VkBool32									depthWriteEnable
1902 		VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp
1903 		VK_FALSE,													// VkBool32									depthBoundsTestEnable
1904 		VK_FALSE,													// VkBool32									stencilTestEnable
1905 		{},															// VkStencilOpState							front
1906 		{},															// VkStencilOpState							back
1907 		0.0f,														// float									minDepthBounds
1908 		1.0f														// float									maxDepthBounds
1909 	};
1910 
1911 	const VkPipelineMultisampleStateCreateInfo	multisampleStateCreateInfo	=
1912 	{
1913 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType
1914 		DE_NULL,													// const void*								pNext
1915 		0u,															// VkPipelineMultisampleStateCreateFlags	flags
1916 		(VkSampleCountFlagBits)m_testParams.sampleCount,			// VkSampleCountFlagBits					rasterizationSamples
1917 		DE_FALSE,													// VkBool32									sampleShadingEnable
1918 		0.0f,														// float									minSampleShading
1919 		&sampleMask,												// const VkSampleMask*						pSampleMask
1920 		m_testParams.alphaToCoverage,								// VkBool32									alphaToCoverageEnable
1921 		DE_FALSE,													// VkBool32									alphaToOneEnable
1922 	};
1923 
1924 	return vk::makeGraphicsPipeline(vk,										// const DeviceInterface&							vk
1925 									device,									// const VkDevice									device
1926 									pipelineLayout,							// const VkPipelineLayout							pipelineLayout
1927 									vertexModule,							// const VkShaderModule								vertexShaderModule
1928 									DE_NULL,								// const VkShaderModule								tessellationControlModule
1929 									DE_NULL,								// const VkShaderModule								tessellationEvalModule
1930 									DE_NULL,								// const VkShaderModule								geometryShaderModule
1931 									fragmentModule,							// const VkShaderModule								fragmentShaderModule
1932 									renderPass,								// const VkRenderPass								renderPass
1933 									viewports,								// const std::vector<VkViewport>&					viewports
1934 									scissors,								// const std::vector<VkRect2D>&						scissors
1935 									VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology						topology
1936 									0u,										// const deUint32									subpass
1937 									0u,										// const deUint32									patchControlPoints
1938 									DE_NULL,								// const VkPipelineVertexInputStateCreateInfo*		vertexInputStateCreateInfo
1939 									DE_NULL,								// const VkPipelineRasterizationStateCreateInfo*	rasterizationStateCreateInfo
1940 									&multisampleStateCreateInfo,			// const VkPipelineMultisampleStateCreateInfo*		multisampleStateCreateInfo
1941 									&depthStencilStateCreateInfo);			// const VkPipelineDepthStencilStateCreateInfo*		depthStencilStateCreateInfo
1942 }
1943 
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const VkFormat depthStencilFormat)1944 Move<VkRenderPass> EarlyFragmentSampleCountTestInstance::makeRenderPass	(const DeviceInterface&	vk,
1945 																		 const VkDevice			device,
1946 																		 const VkFormat			colorFormat,
1947 																		 const VkFormat			depthStencilFormat)
1948 {
1949 	const VkAttachmentDescription			colorAttachmentDescription			=
1950 	{
1951 		(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags	flags;
1952 		colorFormat,										// VkFormat						format;
1953 		(VkSampleCountFlagBits)m_testParams.sampleCount,	// VkSampleCountFlagBits		samples;
1954 		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp			loadOp;
1955 		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp			storeOp;
1956 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp			stencilLoadOp
1957 		VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp			stencilStoreOp
1958 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout				initialLayout
1959 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout				finalLayout
1960 	};
1961 
1962 	const VkAttachmentDescription			depthStencilAttachmentDescription	=
1963 	{
1964 		(VkAttachmentDescriptionFlags)0,					// VkStructureType			sType;
1965 		depthStencilFormat,									// VkFormat					format
1966 		(VkSampleCountFlagBits)m_testParams.sampleCount,	// VkSampleCountFlagBits	samples
1967 		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp		loadOp
1968 		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp		storeOp
1969 		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp		stencilLoadOp
1970 		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp		stencilStoreOp
1971 		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout			initialLayout
1972 		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL	// VkImageLayout			finalLayout
1973 	};
1974 
1975 	const VkAttachmentDescription			resolveAttachmentDescription		=
1976 	{
1977 
1978 		(VkAttachmentDescriptionFlags)0,			// VkSubpassDescriptionFlags	flags
1979 		colorFormat,								// VkFormat						format
1980 		VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits		samples
1981 		VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp			loadOp
1982 		VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp			storeOp
1983 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp			stencilLoadOp
1984 		VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp			stencilStoreOp
1985 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout				initialLayout
1986 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout				finalLayout
1987 	};
1988 
1989 	std::vector<VkAttachmentDescription>	attachmentDescriptions;
1990 
1991 	attachmentDescriptions.push_back(colorAttachmentDescription);
1992 	attachmentDescriptions.push_back(depthStencilAttachmentDescription);
1993 	attachmentDescriptions.push_back(resolveAttachmentDescription);
1994 
1995 	const VkAttachmentReference				colorAttachmentRef					=
1996 	{
1997 		0u,											// deUint32			attachment
1998 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout	layout
1999 	};
2000 
2001 	const VkAttachmentReference				depthStencilAttachmentRef			=
2002 	{
2003 		1u,													// deUint32			attachment
2004 		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout	layout
2005 	};
2006 
2007 	const VkAttachmentReference				resolveAttachmentRef				=
2008 	{
2009 		2u,											// deUint32			attachment
2010 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout	layout
2011 	};
2012 
2013 	const VkSubpassDescription				subpassDescription					=
2014 	{
2015 		(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags		flags
2016 		VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint				pipelineBindPoint
2017 		0u,									// deUint32							inputAttachmentCount
2018 		DE_NULL,							// const VkAttachmentReference2*	pInputAttachments
2019 		1u,									// deUint32							colorAttachmentCount
2020 		&colorAttachmentRef,				// const VkAttachmentReference2*	pColorAttachments
2021 		&resolveAttachmentRef,				// const VkAttachmentReference2*	pResolveAttachments
2022 		&depthStencilAttachmentRef,			// const VkAttachmentReference2*	pDepthStencilAttachment
2023 		0u,									// deUint32							preserveAttachmentCount
2024 		DE_NULL								// const deUint32*					pPreserveAttachments
2025 	};
2026 
2027 	const VkRenderPassCreateInfo			renderPassInfo						=
2028 	{
2029 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType					sType;
2030 		DE_NULL,									// const void*						pNext;
2031 		(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags;
2032 		(deUint32)attachmentDescriptions.size(),	// uint32_t							attachmentCount;
2033 		attachmentDescriptions.data(),				// const VkAttachmentDescription*	pAttachments;
2034 		1u,											// uint32_t							subpassCount;
2035 		&subpassDescription,						// const VkSubpassDescription*		pSubpasses;
2036 		0u,											// uint32_t							dependencyCount;
2037 		DE_NULL										// const VkSubpassDependency*		pDependencies;
2038 	};
2039 
2040 	return createRenderPass(vk, device, &renderPassInfo, DE_NULL);
2041 }
2042 
generateReferenceColorImage(const tcu::TextureFormat format,const tcu::IVec2 & renderSize)2043 tcu::TextureLevel EarlyFragmentSampleCountTestInstance::generateReferenceColorImage(const tcu::TextureFormat format, const tcu::IVec2 &renderSize)
2044 {
2045 	tcu::TextureLevel	image		(format, renderSize.x(), renderSize.y());
2046 	const tcu::Vec4		clearColor	= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
2047 
2048 	tcu::clear(image.getAccess(), clearColor);
2049 
2050 	return image;
2051 }
2052 
iterate(void)2053 tcu::TestStatus EarlyFragmentSampleCountTestInstance::iterate (void)
2054 {
2055 	const DeviceInterface&				vk							= m_context.getDeviceInterface();
2056 	const VkDevice						device						= m_context.getDevice();
2057 	const VkQueue						queue						= m_context.getUniversalQueue();
2058 	const deUint32						queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
2059 	Allocator&							allocator					= m_context.getDefaultAllocator();
2060 	const VkFormat						colorFormat					= VK_FORMAT_R8G8B8A8_UNORM;
2061 	const VkFormat						depthFormat					= VK_FORMAT_D16_UNORM;
2062 	VkQueryPool							queryPool;
2063 	const deUint32						queryCount					= 2u;
2064 	std::vector<VkDeviceSize>			sampleCounts				(queryCount);
2065 
2066 	// Create a query pool for storing the occlusion query result
2067 	{
2068 		VkQueryPoolCreateInfo			queryPoolInfo
2069 		{
2070 			VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,	// VkStructureType					sType;
2071 			DE_NULL,									// const void*						pNext;
2072 			(VkQueryPoolCreateFlags)0,					// VkQueryPoolCreateFlags			flags;
2073 			VK_QUERY_TYPE_OCCLUSION,					// VkQueryType						queryType;
2074 			queryCount,									// uint32_t							queryCount;
2075 			0u,											// VkQueryPipelineStatisticFlags	pipelineStatistics;
2076 		};
2077 
2078 		VK_CHECK(vk.createQueryPool(device, &queryPoolInfo, NULL, &queryPool));
2079 	}
2080 
2081 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth format " << getFormatName(VK_FORMAT_D16_UNORM) << tcu::TestLog::EndMessage;
2082 
2083 	// Color attachment
2084 	const tcu::IVec2					renderSize					= tcu::IVec2(32, 32);
2085 	const VkImageSubresourceRange		colorSubresourceRange		= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
2086 
2087 	const VkImageCreateInfo				imageParams =
2088 	{
2089 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,				// VkStructureType			sType;
2090 		DE_NULL,											// const void*				pNext;
2091 		(VkImageCreateFlags)0,								// VkImageCreateFlags		flags;
2092 		VK_IMAGE_TYPE_2D,									// VkImageType				imageType;
2093 		colorFormat,										// VkFormat					format;
2094 		makeExtent3D(renderSize.x(), renderSize.y(), 1),	// VkExtent3D				extent;
2095 		1u,													// deUint32					mipLevels;
2096 		1u,													// deUint32					arrayLayers;
2097 		(VkSampleCountFlagBits)m_testParams.sampleCount,	// VkSampleCountFlagBits	samples;
2098 		VK_IMAGE_TILING_OPTIMAL,							// VkImageTiling			tiling;
2099 		VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,				// VkImageUsageFlags		usage;
2100 		VK_SHARING_MODE_EXCLUSIVE,							// VkSharingMode			sharingMode;
2101 		0u,													// deUint32					queueFamilyIndexCount;
2102 		DE_NULL,											// const deUint32*			pQueueFamilyIndices;
2103 		VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			initialLayout;
2104 	};
2105 
2106 	const Unique<VkImage>				colorImage					(makeImage(vk, device, imageParams));
2107 	const UniquePtr<Allocation>			colorImageAlloc				(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
2108 	const Unique<VkImageView>			colorImageView				(makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
2109 
2110 	const Unique<VkImage>				resolveColorImage			(makeImage(vk, device, makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
2111 	const UniquePtr<Allocation>			resolveColorImageAlloc		(bindImage(vk, device, allocator, *resolveColorImage, MemoryRequirement::Any));
2112 	const Unique<VkImageView>			resolveColorImageView		(makeImageView(vk, device, *resolveColorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
2113 
2114 	// Depth-Stencil attachment
2115 	const VkImageSubresourceRange		depthSubresourceRange		= makeImageSubresourceRange(getImageAspectFlags(depthFormat), 0u, 1u, 0u, 1u);
2116 
2117 	const VkImageCreateInfo				depthImageParams			=
2118 	{
2119 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,				// VkStructureType			sType;
2120 		DE_NULL,											// const void*				pNext;
2121 		(VkImageCreateFlags)0,								// VkImageCreateFlags		flags;
2122 		VK_IMAGE_TYPE_2D,									// VkImageType				imageType;
2123 		depthFormat,										// VkFormat					format;
2124 		makeExtent3D(renderSize.x(), renderSize.y(), 1),	// VkExtent3D				extent;
2125 		1u,													// deUint32					mipLevels;
2126 		1u,													// deUint32					arrayLayers;
2127 		(VkSampleCountFlagBits)m_testParams.sampleCount,	// VkSampleCountFlagBits	samples;
2128 		VK_IMAGE_TILING_OPTIMAL,							// VkImageTiling			tiling;
2129 		VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,		// VkImageUsageFlags		usage;
2130 		VK_SHARING_MODE_EXCLUSIVE,							// VkSharingMode			sharingMode;
2131 		0u,													// deUint32					queueFamilyIndexCount;
2132 		DE_NULL,											// const deUint32*			pQueueFamilyIndices;
2133 		VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			initialLayout;
2134 	};
2135 
2136 	const Unique<VkImage>				depthImage					(makeImage(vk, device, depthImageParams));
2137 	const UniquePtr<Allocation>			depthImageAlloc				(bindImage(vk, device, allocator, *depthImage, MemoryRequirement::Any));
2138 	const Unique<VkImageView>			depthImageView				(makeImageView(vk, device, *depthImage, VK_IMAGE_VIEW_TYPE_2D, depthFormat, depthSubresourceRange));
2139 
2140 	const VkImageView					attachmentImages[]			= { *colorImageView, *depthImageView, *resolveColorImageView };
2141 	const deUint32						numUsedAttachmentImages		= DE_LENGTH_OF_ARRAY(attachmentImages);
2142 
2143 	// Vertex buffer
2144 	const deUint32						numVertices					= 6u;
2145 	const VkDeviceSize					vertexBufferSizeBytes		= 256 * numVertices;
2146 	const Unique<VkBuffer>				vertexBuffer				(makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
2147 	const UniquePtr<Allocation>			vertexBufferAlloc			(bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
2148 
2149 	{
2150 		tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
2151 
2152 		pVertices[0] = tcu::Vec4( 1.0f, -1.0f,  0.0f,  1.0f);
2153 		pVertices[1] = tcu::Vec4(-1.0f, -1.0f,  0.0f,  1.0f);
2154 		pVertices[2] = tcu::Vec4(-1.0f,  1.0f,  0.0f,  1.0f);
2155 
2156 		pVertices[3] = tcu::Vec4(-1.0f,  1.0f,  1.0f,  1.0f);
2157 		pVertices[4] = tcu::Vec4( 1.0f,  1.0f,  1.0f,  1.0f);
2158 		pVertices[5] = tcu::Vec4( 1.0f, -1.0f,  1.0f,  1.0f);
2159 
2160 		flushAlloc(vk, device, *vertexBufferAlloc);
2161 		// No barrier needed, flushed memory is automatically visible
2162 	}
2163 
2164 	// Render result buffer (to retrieve color attachment contents)
2165 
2166 	const VkDeviceSize					colorBufferSizeBytes		= tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
2167 	const Unique<VkBuffer>				colorBufferNoEarlyResults	(makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
2168 	const UniquePtr<Allocation>			colorBufferAllocNoEarly		(bindBuffer(vk, device, allocator, *colorBufferNoEarlyResults, MemoryRequirement::HostVisible));
2169 	const Unique<VkBuffer>				colorBufferEarlyResults		(makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
2170 	const UniquePtr<Allocation>			colorBufferAllocEarly		(bindBuffer(vk, device, allocator, *colorBufferEarlyResults, MemoryRequirement::HostVisible));
2171 
2172 	// Pipeline
2173 
2174 	const Unique<VkShaderModule>		vertexModule				(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
2175 	const Unique<VkShaderModule>		fragmentModuleNoEarly		(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
2176 	const Unique<VkShaderModule>		fragmentModuleEarlyFrag		(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag_early"), 0u));
2177 
2178 	const Unique<VkRenderPass>			renderPass					(makeRenderPass(vk, device, colorFormat, depthFormat));
2179 
2180 	const Unique<VkFramebuffer>			framebuffer					(makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages, renderSize.x(), renderSize.y()));
2181 
2182 	const Unique<VkPipelineLayout>		pipelineLayout				(makePipelineLayout(vk, device, DE_NULL));
2183 
2184 	// When we are creating a pipeline for runs without early fragment test, we are enabling all the samples for full coverage.
2185 	// Sample mask will be modified in a fragment shader.
2186 	const Unique<VkPipeline>			pipelineNoEarlyFrag			(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModuleNoEarly, renderSize, 0xFFFFFFFF));
2187 
2188 	// For early fragment tests, we are enabling only half of the samples.
2189 	const Unique<VkPipeline>			pipelineEarlyFrag			(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModuleEarlyFrag, renderSize, 0xAAAAAAAA));
2190 
2191 	// Build a command buffer
2192 
2193 	const Unique<VkCommandPool>			cmdPool						(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
2194 	const Unique<VkCommandBuffer>		cmdBuffer					(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2195 
2196 	enum QueryIndex
2197 	{
2198 		QUERY_INDEX_NO_EARLY_FRAG = 0,
2199 		QUERY_INDEX_EARLY_FRAG = 1
2200 	};
2201 
2202 	{
2203 		const VkRect2D					renderArea					=
2204 		{
2205 			makeOffset2D(0, 0),
2206 			makeExtent2D(renderSize.x(), renderSize.y()),
2207 		};
2208 
2209 		const tcu::Vec4					clearColor					(0.0f, 0.0f, 0.0f, 1.0f);
2210 		const VkDeviceSize				vertexBufferOffset			= 0ull;
2211 
2212 		beginCommandBuffer(vk, *cmdBuffer);
2213 
2214 		// transition images to proper layouts - this cant be done with renderpass as we will use same renderpass twice
2215 		const VkImageMemoryBarrier initialImageBarriers[]
2216 		{
2217 			makeImageMemoryBarrier(0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
2218 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresourceRange),
2219 			makeImageMemoryBarrier(0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
2220 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *resolveColorImage, colorSubresourceRange),
2221 			makeImageMemoryBarrier(0, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
2222 				VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *depthImage, depthSubresourceRange)
2223 		};
2224 		vk.cmdPipelineBarrier(*cmdBuffer, 0, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 2u, initialImageBarriers);
2225 		vk.cmdPipelineBarrier(*cmdBuffer, 0, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &initialImageBarriers[2]);
2226 
2227 		const VkClearValue				clearValues[]				=
2228 		{
2229 			makeClearValueColor(clearColor),		// attachment 0
2230 			makeClearValueDepthStencil(0.5f, 3u),	// attachment 1
2231 			makeClearValueColor(clearColor),		// attachment 2
2232 			makeClearValueDepthStencil(0.5f, 3u),	// attachment 3
2233 		};
2234 
2235 		const VkRenderPassBeginInfo		renderPassBeginInfo			=
2236 		{
2237 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,	// VkStructureType		sType;
2238 			DE_NULL,									// const void*			pNext;
2239 			*renderPass,								// VkRenderPass			renderPass;
2240 			*framebuffer,								// VkFramebuffer		framebuffer;
2241 			renderArea,									// VkRect2D				renderArea;
2242 			DE_LENGTH_OF_ARRAY(clearValues),			// deUint32				clearValueCount;
2243 			clearValues,								// const VkClearValue*	pClearValues;
2244 		};
2245 
2246 		// Reset query pool. Must be done outside of render pass
2247 		vk.cmdResetQueryPool(*cmdBuffer, queryPool, 0, queryCount);
2248 
2249 		vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
2250 
2251 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
2252 
2253 		// Run without early fragment test.
2254 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineNoEarlyFrag);
2255 
2256 		vk.cmdBeginQuery(cmdBuffer.get(), queryPool, QUERY_INDEX_NO_EARLY_FRAG, VK_QUERY_CONTROL_PRECISE_BIT);
2257 		vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
2258 		vk.cmdEndQuery(cmdBuffer.get(), queryPool, QUERY_INDEX_NO_EARLY_FRAG);
2259 
2260 		endRenderPass(vk, *cmdBuffer);
2261 
2262 		copyImageToBuffer(vk, *cmdBuffer, *resolveColorImage, *colorBufferNoEarlyResults, renderSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
2263 
2264 		// after copying from resolved image we need to switch its layout back to color attachment optimal
2265 		const VkImageMemoryBarrier postResolveImageBarrier = makeImageMemoryBarrier(VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
2266 			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *resolveColorImage, colorSubresourceRange);
2267 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &postResolveImageBarrier);
2268 
2269 		vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
2270 
2271 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
2272 
2273 		// Run with early fragment test.
2274 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineEarlyFrag);
2275 
2276 		vk.cmdBeginQuery(cmdBuffer.get(), queryPool, QUERY_INDEX_EARLY_FRAG, VK_QUERY_CONTROL_PRECISE_BIT);
2277 		vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
2278 		vk.cmdEndQuery(cmdBuffer.get(), queryPool, QUERY_INDEX_EARLY_FRAG);
2279 
2280 		endRenderPass(vk, *cmdBuffer);
2281 
2282 		copyImageToBuffer(vk, *cmdBuffer, *resolveColorImage, *colorBufferEarlyResults, renderSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
2283 
2284 		endCommandBuffer(vk, *cmdBuffer);
2285 		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
2286 	}
2287 
2288 	// When early fragment test is enabled, all samples are killed in fragment shader. The result color should be black.
2289 	{
2290 		invalidateAlloc(vk, device, *colorBufferAllocEarly);
2291 
2292 		const tcu::ConstPixelBufferAccess	imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAllocEarly->getHostPtr());
2293 		const tcu::TextureLevel				referenceImage = generateReferenceColorImage(mapVkFormat(colorFormat), renderSize);
2294 
2295 		if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare color output", "Early fragment image result comparison", referenceImage.getAccess(), imagePixelAccess, tcu::Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
2296 			return tcu::TestStatus::fail("Rendered color image is not correct");
2297 	}
2298 
2299 	// The image has 32x32 pixels and each pixel has m_sampleCount samples. Half of these samples are discarded before sample counting.
2300 	// This means the reference value for passed samples is ((32 x 32) / 2 / 2) * sampleCount.
2301 	{
2302 		deUint64	refValue	= deUint64(deUint32((renderSize.x() * renderSize.y()) / 4) * m_testParams.sampleCount);
2303 		deUint64	tolerance	= deUint64(refValue * 5 / 100);
2304 		deUint64	minValue	= refValue - tolerance;
2305 		deUint64	maxValue	= refValue + tolerance;
2306 
2307 		VK_CHECK(vk.getQueryPoolResults(device, queryPool, 0u, queryCount, queryCount * sizeof(VkDeviceSize), sampleCounts.data(), sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
2308 
2309 		// Log test results
2310 		{
2311 			tcu::TestLog& log = m_context.getTestContext().getLog();
2312 
2313 			log << tcu::TestLog::Message << "\nAcceptable range: " << minValue << " - " << maxValue << tcu::TestLog::EndMessage;
2314 			log << tcu::TestLog::Message << "Passed Samples (without early fragment test) : " << de::toString(sampleCounts[0]) << tcu::TestLog::EndMessage;
2315 			log << tcu::TestLog::Message << "Passed Samples (with early fragment test)    : " << de::toString(sampleCounts[1]) << tcu::TestLog::EndMessage;
2316 		}
2317 
2318 #ifndef CTS_USES_VULKANSC
2319 		vk.destroyQueryPool(device, queryPool, nullptr);
2320 #endif // CTS_USES_VULKANSC
2321 
2322 		// Check that number of the all passed samples are within an acceptable range.
2323 		if (sampleCounts[QUERY_INDEX_NO_EARLY_FRAG] >= minValue && sampleCounts[QUERY_INDEX_NO_EARLY_FRAG] <= maxValue && sampleCounts[QUERY_INDEX_EARLY_FRAG] >= minValue && sampleCounts[QUERY_INDEX_EARLY_FRAG] <= maxValue)
2324 		{
2325 			return tcu::TestStatus::pass("Success");
2326 		}
2327 		else if (sampleCounts[QUERY_INDEX_NO_EARLY_FRAG] >= minValue && sampleCounts[QUERY_INDEX_NO_EARLY_FRAG] <= maxValue && sampleCounts[QUERY_INDEX_EARLY_FRAG] == 0)
2328 		{
2329 #ifndef CTS_USES_VULKANSC
2330 			if (m_testParams.useMaintenance5)
2331 			{
2332 				if (m_context.getMaintenance5Properties().earlyFragmentMultisampleCoverageAfterSampleCounting)
2333 					return tcu::TestStatus::fail("Fail");
2334 				return tcu::TestStatus::pass("Pass");
2335 			}
2336 #endif
2337 			// Spec says: "If the fragment shader declares the EarlyFragmentTests execution mode, fragment shading and
2338 			// multisample coverage operations should instead be performed after sample counting.
2339 
2340 			// since the specification says 'should', the opposite behavior is allowed, but not preferred
2341 			return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Sample count is 0 - sample counting performed after multisample coverage and fragment shading");
2342 		}
2343 		else if (sampleCounts[QUERY_INDEX_NO_EARLY_FRAG] >= minValue && sampleCounts[QUERY_INDEX_NO_EARLY_FRAG] <= maxValue &&
2344 					sampleCounts[QUERY_INDEX_EARLY_FRAG] >= (minValue * 2) && sampleCounts[QUERY_INDEX_EARLY_FRAG] <= (maxValue * 2))
2345 		{
2346 			// If the sample count returned is double the expected value, the sample mask test has been executed after
2347 			// sample counting.
2348 
2349 #ifndef CTS_USES_VULKANSC
2350 			if (m_testParams.useMaintenance5)
2351 			{
2352 				if (m_context.getMaintenance5Properties().earlyFragmentSampleMaskTestBeforeSampleCounting)
2353 					return tcu::TestStatus::fail("Fail");
2354 				return tcu::TestStatus::pass("Pass");
2355 			}
2356 #endif
2357 			// Spec says: "If there is a fragment shader and it declares the EarlyFragmentTests execution mode, ...
2358 			// sample mask test may: instead be performed after sample counting"
2359 
2360 			// since the specification says 'may', the opposite behavior is allowed, but not preferred
2361 			return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Sample count is greater than expected - sample mask test performed after sample counting");
2362 		}
2363 		else
2364 		{
2365 			// Log no early frag test images
2366 			{
2367 				tcu::TestLog& log = m_context.getTestContext().getLog();
2368 
2369 				invalidateAlloc(vk, device, *colorBufferAllocNoEarly);
2370 
2371 				const tcu::ConstPixelBufferAccess	imagePixelAccess	(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAllocNoEarly->getHostPtr());
2372 
2373 				log << tcu::LogImageSet("No Early Frag Test Images", "No Early Fragment Test Images")
2374 					<< tcu::TestLog::Image("color", "Rendered image (color)", imagePixelAccess)
2375 					<< tcu::TestLog::EndImageSet;
2376 			}
2377 
2378 			// Log early frag test images
2379 			{
2380 				tcu::TestLog& log = m_context.getTestContext().getLog();
2381 
2382 				invalidateAlloc(vk, device, *colorBufferAllocEarly);
2383 
2384 				const tcu::ConstPixelBufferAccess	imagePixelAccess	(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAllocEarly->getHostPtr());
2385 
2386 				log << tcu::LogImageSet("Early Frag Test Images", "Early Fragment Test Images")
2387 					<< tcu::TestLog::Image("color", "Rendered image (color)", imagePixelAccess)
2388 					<< tcu::TestLog::EndImageSet;
2389 			}
2390 
2391 			return tcu::TestStatus::fail("Sample count value outside expected range.");
2392 		}
2393 	}
2394 }
2395 
2396 class EarlyFragmentSampleCountTest : public EarlyFragmentTest
2397 {
2398 public:
2399 	EarlyFragmentSampleCountTest		(tcu::TestContext&				testCtx,
2400 										 const std::string				name,
2401 										 const SampleCountTestParams&	testParams);
2402 
2403 	void				initPrograms	(SourceCollections& programCollection) const override;
2404 	TestInstance*		createInstance	(Context& context) const override;
2405 	void				checkSupport	(Context& context) const override;
2406 
2407 private:
2408 	const SampleCountTestParams m_testParams;
2409 };
2410 
EarlyFragmentSampleCountTest(tcu::TestContext & testCtx,const std::string name,const SampleCountTestParams & testParams)2411 EarlyFragmentSampleCountTest::EarlyFragmentSampleCountTest(tcu::TestContext& testCtx, const std::string name, const SampleCountTestParams& testParams)
2412 	: EarlyFragmentTest	(testCtx, name, FLAG_TEST_DEPTH)
2413 	, m_testParams		(testParams)
2414 {
2415 }
2416 
createInstance(Context & context) const2417 TestInstance* EarlyFragmentSampleCountTest::createInstance (Context& context) const
2418 {
2419 	return new EarlyFragmentSampleCountTestInstance(context, m_testParams);
2420 }
2421 
initPrograms(SourceCollections & programCollection) const2422 void EarlyFragmentSampleCountTest::initPrograms(SourceCollections& programCollection) const
2423 {
2424 	// Vertex shader
2425 	{
2426 		std::ostringstream vrt;
2427 
2428 		vrt << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2429 			<< "\n"
2430 			<< "layout(location = 0) in highp vec4 position;\n"
2431 			<< "\n"
2432 			<< "out gl_PerVertex {\n"
2433 			<< "   vec4 gl_Position;\n"
2434 			<< "};\n"
2435 			<< "\n"
2436 			<< "void main (void)\n"
2437 			<< "{\n"
2438 			<< "    gl_Position = position;\n"
2439 			<< "}\n";
2440 
2441 		programCollection.glslSources.add("vert") << glu::VertexSource(vrt.str());
2442 	}
2443 
2444 	// Fragment shader for runs without early fragment test
2445 	if (m_testParams.earlyAndLate == false)
2446 	{
2447 		std::ostringstream frg;
2448 
2449 		frg << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2450 			<< "\n"
2451 			<< "layout(location = 0) out highp vec4 fragColor;\n"
2452 			<< "\n"
2453 			<< "void main (void)\n"
2454 			<< "{\n"
2455 			<< "    // This will kill half of the samples.\n"
2456 			<< "    gl_SampleMask[0] = 0xAAAAAAAA;\n"
2457 			<< "    fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
2458 			<< "}\n";
2459 
2460 		programCollection.glslSources.add("frag") << glu::FragmentSource(frg.str());
2461 	}
2462 	else
2463 	{
2464 		const SpirVAsmBuildOptions	buildOptionsSpr(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3);
2465 		const std::string			src =
2466 			"; SPIR - V\n"
2467 			"; Version: 1.0\n"
2468 			"; Generator: Khronos Glslang Reference Front End; 10\n"
2469 			"; Bound: 23\n"
2470 			"; Schema: 0\n"
2471 			"OpCapability Shader\n"
2472 			"OpExtension \"SPV_AMD_shader_early_and_late_fragment_tests\"\n"
2473 			"%1 = OpExtInstImport \"GLSL.std.450\"\n"
2474 			"OpMemoryModel Logical GLSL450\n"
2475 			"OpEntryPoint Fragment %4 \"main\" %11 %19\n"
2476 			"OpExecutionMode %4 OriginUpperLeft\n"
2477 			"OpExecutionMode %4 EarlyAndLateFragmentTestsAMD\n"
2478 			"OpExecutionMode %4 DepthReplacing\n"
2479 			"OpExecutionMode %4 DepthLess\n"
2480 			"OpDecorate %11 BuiltIn SampleMask\n"
2481 			"OpDecorate %19 Location 0\n"
2482 			"%2 = OpTypeVoid\n"
2483 			"%3 = OpTypeFunction %2\n"
2484 			"%6 = OpTypeInt 32 1\n"
2485 			"%7 = OpTypeInt 32 0\n"
2486 			"%8 = OpConstant %7 1\n"
2487 			"%9 = OpTypeArray %6 %8\n"
2488 			"%10 = OpTypePointer Output %9\n"
2489 			"%11 = OpVariable %10 Output\n"
2490 			"%12 = OpConstant %6 0\n"
2491 			"%13 = OpConstant %6 -1431655766\n"
2492 			"%14 = OpTypePointer Output %6\n"
2493 			"%16 = OpTypeFloat 32\n"
2494 			"%17 = OpTypeVector %16 4\n"
2495 			"%18 = OpTypePointer Output %17\n"
2496 			"%19 = OpVariable %18 Output\n"
2497 			"%20 = OpConstant %16 1\n"
2498 			"%21 = OpConstant %16 0\n"
2499 			"%22 = OpConstantComposite %17 %20 %20 %21 %20\n"
2500 			"%4 = OpFunction %2 None %3\n"
2501 			"%5 = OpLabel\n"
2502 			"%15 = OpAccessChain %14 %11 %12\n"
2503 			"OpStore %15 %13\n"
2504 			"OpStore %19 %22\n"
2505 			"OpReturn\n"
2506 			"OpFunctionEnd\n";
2507 		programCollection.spirvAsmSources.add("frag") << src << buildOptionsSpr;
2508 	}
2509 
2510 	// Fragment shader for early fragment tests
2511 	if (m_testParams.earlyAndLate == false)
2512 	{
2513 		std::ostringstream frg;
2514 
2515 		frg << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2516 			<< "\n"
2517 			<< "layout(early_fragment_tests) in;\n"
2518 			<< "\n"
2519 			<< "layout(location = 0) out highp vec4 fragColor;\n"
2520 			<< "\n"
2521 			<< "void main (void)\n"
2522 			<< "{\n";
2523 
2524 		if (m_testParams.alphaToCoverage)
2525 		{
2526 			frg << "    // alphaToCoverageEnable = TRUE and emitting 0 alpha kills all the samples, but the sample counting has already happened.\n"
2527 				<< "    fragColor = vec4(1.0, 1.0, 0.0, 0.0);\n"
2528 				<< "}\n";
2529 		}
2530 		else
2531 		{
2532 			frg << "    // Sample mask kills all the samples, but the sample counting has already happened.\n"
2533 				<< "    gl_SampleMask[0] = 0x0;\n"
2534 				<< "    fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
2535 				<< "}\n";
2536 		}
2537 
2538 		programCollection.glslSources.add("frag_early") << glu::FragmentSource(frg.str());
2539 	}
2540 	else
2541 	{
2542 		const SpirVAsmBuildOptions	buildOptionsSpr(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3);
2543 		const std::string			src	=
2544 			"; SPIR - V\n"
2545 			"; Version: 1.0\n"
2546 			"; Generator: Khronos Glslang Reference Front End; 10\n"
2547 			"; Bound: 22\n"
2548 			"; Schema: 0\n"
2549 			"OpCapability Shader\n"
2550 			"OpExtension \"SPV_AMD_shader_early_and_late_fragment_tests\"\n"
2551 			"%1 = OpExtInstImport \"GLSL.std.450\"\n"
2552 			"OpMemoryModel Logical GLSL450\n"
2553 			"OpEntryPoint Fragment %4 \"main\" %11 %18\n"
2554 			"OpExecutionMode %4 OriginUpperLeft\n"
2555 			"OpExecutionMode %4 EarlyAndLateFragmentTestsAMD\n"
2556 			"OpDecorate %11 BuiltIn SampleMask\n"
2557 			"OpDecorate %18 Location 0\n"
2558 			"%2 = OpTypeVoid\n"
2559 			"%3 = OpTypeFunction %2\n"
2560 			"%6 = OpTypeInt 32 1\n"
2561 			"%7 = OpTypeInt 32 0\n"
2562 			"%8 = OpConstant %7 1\n"
2563 			"%9 = OpTypeArray %6 %8\n"
2564 			"%10 = OpTypePointer Output %9\n"
2565 			"%11 = OpVariable %10 Output\n"
2566 			"%12 = OpConstant %6 0\n"
2567 			"%13 = OpTypePointer Output %6\n"
2568 			"%15 = OpTypeFloat 32\n"
2569 			"%16 = OpTypeVector %15 4\n"
2570 			"%17 = OpTypePointer Output %16\n"
2571 			"%18 = OpVariable %17 Output\n"
2572 			"%19 = OpConstant %15 1\n"
2573 			"%20 = OpConstant %15 0\n"
2574 			"%21 = OpConstantComposite %16 %19 %19 %20 %19\n"
2575 			"%4 = OpFunction %2 None %3\n"
2576 			"%5 = OpLabel\n"
2577 			"%14 = OpAccessChain %13 %11 %12\n"
2578 			"OpStore %14 %12\n"
2579 			"OpStore %18 %21\n"
2580 			"OpReturn\n"
2581 			"OpFunctionEnd\n";
2582 		programCollection.spirvAsmSources.add("frag_early") << src << buildOptionsSpr;
2583 	}
2584 }
2585 
checkSupport(Context & context) const2586 void EarlyFragmentSampleCountTest::checkSupport(Context& context) const
2587 {
2588 	EarlyFragmentTest::checkSupport(context);
2589 
2590 	// Check support for MSAA image formats used in the test.
2591 	const InstanceInterface&	vki				= context.getInstanceInterface();
2592 	const VkPhysicalDevice		physDevice		= context.getPhysicalDevice();
2593 	const VkFormat				colorFormat		= VK_FORMAT_R8G8B8A8_UNORM;
2594 	const VkFormat				depthFormat		= VK_FORMAT_D16_UNORM;
2595 
2596 	VkImageFormatProperties		formatProperties;
2597 
2598 	vki.getPhysicalDeviceImageFormatProperties(physDevice, colorFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u, &formatProperties);
2599 	if ((formatProperties.sampleCounts & m_testParams.sampleCount) == 0)
2600 		TCU_THROW(NotSupportedError, "Format does not support this number of samples for color format");
2601 
2602 	vki.getPhysicalDeviceImageFormatProperties(physDevice, depthFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u, &formatProperties);
2603 	if ((formatProperties.sampleCounts & m_testParams.sampleCount) == 0)
2604 		TCU_THROW(NotSupportedError, "Format does not support this number of samples for depth format");
2605 
2606 #ifndef CTS_USES_VULKANSC
2607 	if (m_testParams.earlyAndLate)
2608 	{
2609 		context.requireDeviceFunctionality("VK_AMD_shader_early_and_late_fragment_tests");
2610 		if (context.getShaderEarlyAndLateFragmentTestsFeaturesAMD().shaderEarlyAndLateFragmentTests == VK_FALSE)
2611 			TCU_THROW(NotSupportedError, "shaderEarlyAndLateFragmentTests is not supported");
2612 	}
2613 
2614 	if (m_testParams.useMaintenance5)
2615 		context.requireDeviceFunctionality("VK_KHR_maintenance5");
2616 #endif
2617 }
2618 
2619 } // anonymous ns
2620 
createEarlyFragmentTests(tcu::TestContext & testCtx)2621 tcu::TestCaseGroup* createEarlyFragmentTests (tcu::TestContext& testCtx)
2622 {
2623 	de::MovePtr<tcu::TestCaseGroup> testGroup			(new tcu::TestCaseGroup(testCtx, "early_fragment"));
2624 
2625 	{
2626 		struct TestCaseEarly
2627 		{
2628 			std::string caseName;
2629 			deUint32	flags;
2630 		};
2631 
2632 		static const TestCaseEarly cases[] =
2633 		{
2634 
2635 			{ "no_early_fragment_tests_depth",					FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS									},
2636 			{ "no_early_fragment_tests_stencil",				FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS									},
2637 			{ "early_fragment_tests_depth",						FLAG_TEST_DEPTH																			},
2638 			{ "early_fragment_tests_stencil",					FLAG_TEST_STENCIL																		},
2639 			{ "no_early_fragment_tests_depth_no_attachment",	FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT	},
2640 			{ "no_early_fragment_tests_stencil_no_attachment",	FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT	},
2641 			{ "early_fragment_tests_depth_no_attachment",		FLAG_TEST_DEPTH   | FLAG_DONT_USE_TEST_ATTACHMENT										},
2642 			{ "early_fragment_tests_stencil_no_attachment",		FLAG_TEST_STENCIL | FLAG_DONT_USE_TEST_ATTACHMENT										},
2643 		};
2644 
2645 #ifndef CTS_USES_VULKANSC
2646 		static const TestCaseEarly casesEarlyAndLate[] =
2647 		{
2648 			{ "early_and_late_fragment_tests_depth",				FLAG_TEST_DEPTH   | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS									},
2649 			{ "early_and_late_fragment_tests_stencil",				FLAG_TEST_STENCIL | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS									},
2650 			{ "early_and_late_fragment_tests_depth_no_attachment",	FLAG_TEST_DEPTH   | FLAG_DONT_USE_TEST_ATTACHMENT | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS	},
2651 			{ "early_and_late_fragment_tests_stencil_no_attachment",FLAG_TEST_STENCIL | FLAG_DONT_USE_TEST_ATTACHMENT | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS	},
2652 		};
2653 #endif
2654 
2655 		for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
2656 			testGroup->addChild(new EarlyFragmentTest(testCtx, cases[i].caseName, cases[i].flags));
2657 #ifndef CTS_USES_VULKANSC
2658 		for (int i = 0; i < DE_LENGTH_OF_ARRAY(casesEarlyAndLate); ++i)
2659 			testGroup->addChild(new EarlyFragmentTest(testCtx, casesEarlyAndLate[i].caseName, casesEarlyAndLate[i].flags));
2660 #endif
2661 	}
2662 
2663 	// Check that discard does not affect depth test writes.
2664 	{
2665 		static const struct
2666 		{
2667 			std::string caseName;
2668 			deUint32	flags;
2669 		} cases[] =
2670 		{
2671 			{ "discard_no_early_fragment_tests_depth",			FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS										},
2672 			{ "discard_no_early_fragment_tests_stencil",		FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS										},
2673 			{ "discard_early_fragment_tests_depth",				FLAG_TEST_DEPTH																				},
2674 			{ "discard_early_fragment_tests_stencil",			FLAG_TEST_STENCIL																			},
2675 #ifndef CTS_USES_VULKANSC
2676 			{ "discard_early_and_late_fragment_tests_depth",	FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS	},
2677 			{ "discard_early_and_late_fragment_tests_stencil",	FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS	},
2678 #endif
2679 		};
2680 
2681 		for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
2682 			testGroup->addChild(new EarlyFragmentDiscardTest(testCtx, cases[i].caseName, cases[i].flags));
2683 	}
2684 
2685 	// Check that writing to gl_SampleMask does not affect depth test writes.
2686 	{
2687 		static const struct
2688 		{
2689 			std::string caseName;
2690 			deUint32	flags;
2691 		} cases[] =
2692 		{
2693 			{ "samplemask_no_early_fragment_tests_depth",						FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS										},
2694 			{ "samplemask_early_fragment_tests_depth",							FLAG_TEST_DEPTH																				},
2695 #ifndef CTS_USES_VULKANSC
2696 			{ "samplemask_early_and_late_fragment_tests_depth_replacing_mode",	FLAG_TEST_DEPTH | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS	},
2697 			{ "samplemask_early_and_late_fragment_tests_depth",					FLAG_TEST_DEPTH | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS										},
2698 #endif
2699 		};
2700 
2701 		const VkSampleCountFlags sampleCounts[] = { VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT, VK_SAMPLE_COUNT_16_BIT };
2702 		const std::string sampleCountsStr[] = { "samples_2", "samples_4", "samples_8", "samples_16" };
2703 
2704 		for (deUint32 sampleCountsNdx = 0; sampleCountsNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountsNdx++)
2705 		{
2706 			for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
2707 				testGroup->addChild(new EarlyFragmentSampleMaskTest(testCtx, cases[i].caseName + "_" + sampleCountsStr[sampleCountsNdx], cases[i].flags, sampleCounts[sampleCountsNdx]));
2708 		}
2709 	}
2710 
2711 	// We kill half of the samples at different points in the pipeline depending on early frag test, and then we verify the sample counting works as expected.
2712 	{
2713 		const VkSampleCountFlags	sampleCounts[]		= { VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT, VK_SAMPLE_COUNT_16_BIT };
2714 		const std::string			sampleCountsStr[]	= { "samples_2", "samples_4", "samples_8", "samples_16" };
2715 
2716 		for (deUint32 sampleCountsNdx = 0; sampleCountsNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountsNdx++)
2717 		{
2718 			SampleCountTestParams params
2719 			{
2720 				sampleCounts[sampleCountsNdx],	// deUint32	sampleCount;
2721 				false,							// bool		earlyAndLate;
2722 				false,							// bool		alphaToCoverage;
2723 				false,							// bool		useMaintenance5;
2724 			};
2725 
2726 			testGroup->addChild(new EarlyFragmentSampleCountTest(testCtx, "sample_count_early_fragment_tests_depth_" + sampleCountsStr[sampleCountsNdx], params));
2727 #ifndef CTS_USES_VULKANSC
2728 			params.earlyAndLate = true;
2729 			testGroup->addChild(new EarlyFragmentSampleCountTest(testCtx, "sample_count_early_and_late_fragment_tests_depth_" + sampleCountsStr[sampleCountsNdx], params));
2730 
2731 			params.useMaintenance5 = true;
2732 			testGroup->addChild(new EarlyFragmentSampleCountTest(testCtx, "sample_count_early_and_late_fragment_tests_depth_" + sampleCountsStr[sampleCountsNdx] + "_maintenance5", params));
2733 			params.earlyAndLate = false;
2734 			testGroup->addChild(new EarlyFragmentSampleCountTest(testCtx, "sample_count_early_fragment_tests_depth_" + sampleCountsStr[sampleCountsNdx] + "_maintenance5", params));
2735 			params.alphaToCoverage = true;
2736 			testGroup->addChild(new EarlyFragmentSampleCountTest(testCtx, "sample_count_early_fragment_tests_depth_alpha_to_coverage_" + sampleCountsStr[sampleCountsNdx] + "_maintenance5", params));
2737 #endif
2738 		}
2739 	}
2740 
2741 	return testGroup.release();
2742 }
2743 
2744 } // FragmentOperations
2745 } // vkt
2746