• 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 	    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 	    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 class EarlyFragmentSampleCountTestInstance : public EarlyFragmentTestInstance
1843 {
1844 public:
1845 						EarlyFragmentSampleCountTestInstance	(Context& context, const deUint32 sampleCount);
1846 
1847 	tcu::TestStatus		iterate									(void);
1848 
1849 private:
1850 	tcu::TextureLevel	generateReferenceColorImage				(const tcu::TextureFormat format, const tcu::IVec2& renderSize);
1851 
1852 	Move<VkRenderPass>	makeRenderPass							(const DeviceInterface&		vk,
1853 																 const VkDevice				device,
1854 																 const VkFormat				colorFormat,
1855 																 const VkFormat				depthStencilFormat);
1856 
1857 	Move<VkPipeline>	makeGraphicsPipeline					(const DeviceInterface&		vk,
1858 																 const VkDevice				device,
1859 																 const VkPipelineLayout		pipelineLayout,
1860 																 const VkRenderPass			renderPass,
1861 																 const VkShaderModule		vertexModule,
1862 																 const VkShaderModule		fragmentModule,
1863 																 const tcu::IVec2&			renderSize,
1864 																 const VkSampleMask			sampleMask);
1865 
1866 	const deUint32		m_sampleCount;
1867 };
1868 
EarlyFragmentSampleCountTestInstance(Context & context,const deUint32 sampleCount)1869 EarlyFragmentSampleCountTestInstance::EarlyFragmentSampleCountTestInstance (Context& context, const deUint32 sampleCount)
1870 	: EarlyFragmentTestInstance	(context, FLAG_TEST_DEPTH)
1871 	, m_sampleCount				(sampleCount)
1872 {
1873 }
1874 
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)1875 Move<VkPipeline> EarlyFragmentSampleCountTestInstance::makeGraphicsPipeline	(const DeviceInterface&	vk,
1876 																			const VkDevice			device,
1877 																			const VkPipelineLayout	pipelineLayout,
1878 																			const VkRenderPass		renderPass,
1879 																			const VkShaderModule	vertexModule,
1880 																			const VkShaderModule	fragmentModule,
1881 																			const tcu::IVec2&		renderSize,
1882 																			const VkSampleMask		sampleMask)
1883 {
1884 	const std::vector<VkViewport>				viewports					(1, makeViewport(renderSize));
1885 	const std::vector<VkRect2D>					scissors					(1, makeRect2D(renderSize));
1886 
1887 	const VkPipelineDepthStencilStateCreateInfo	depthStencilStateCreateInfo	=
1888 	{
1889 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType
1890 		DE_NULL,													// const void*								pNext
1891 		0u,															// VkPipelineDepthStencilStateCreateFlags	flags
1892 		VK_TRUE,													// VkBool32									depthTestEnable
1893 		VK_TRUE,													// VkBool32									depthWriteEnable
1894 		VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp
1895 		VK_FALSE,													// VkBool32									depthBoundsTestEnable
1896 		VK_FALSE,													// VkBool32									stencilTestEnable
1897 		{},															// VkStencilOpState							front
1898 		{},															// VkStencilOpState							back
1899 		0.0f,														// float									minDepthBounds
1900 		1.0f														// float									maxDepthBounds
1901 	};
1902 
1903 	const VkPipelineMultisampleStateCreateInfo	multisampleStateCreateInfo	=
1904 	{
1905 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType
1906 		DE_NULL,													// const void*								pNext
1907 		0u,															// VkPipelineMultisampleStateCreateFlags	flags
1908 		(VkSampleCountFlagBits)m_sampleCount,						// VkSampleCountFlagBits					rasterizationSamples
1909 		DE_FALSE,													// VkBool32									sampleShadingEnable
1910 		0.0f,														// float									minSampleShading
1911 		&sampleMask,												// const VkSampleMask*						pSampleMask
1912 		DE_FALSE,													// VkBool32									alphaToCoverageEnable
1913 		DE_FALSE,													// VkBool32									alphaToOneEnable
1914 	};
1915 
1916 	return vk::makeGraphicsPipeline(vk,										// const DeviceInterface&							vk
1917 									device,									// const VkDevice									device
1918 									pipelineLayout,							// const VkPipelineLayout							pipelineLayout
1919 									vertexModule,							// const VkShaderModule								vertexShaderModule
1920 									DE_NULL,								// const VkShaderModule								tessellationControlModule
1921 									DE_NULL,								// const VkShaderModule								tessellationEvalModule
1922 									DE_NULL,								// const VkShaderModule								geometryShaderModule
1923 									fragmentModule,							// const VkShaderModule								fragmentShaderModule
1924 									renderPass,								// const VkRenderPass								renderPass
1925 									viewports,								// const std::vector<VkViewport>&					viewports
1926 									scissors,								// const std::vector<VkRect2D>&						scissors
1927 									VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology						topology
1928 									0u,										// const deUint32									subpass
1929 									0u,										// const deUint32									patchControlPoints
1930 									DE_NULL,								// const VkPipelineVertexInputStateCreateInfo*		vertexInputStateCreateInfo
1931 									DE_NULL,								// const VkPipelineRasterizationStateCreateInfo*	rasterizationStateCreateInfo
1932 									&multisampleStateCreateInfo,			// const VkPipelineMultisampleStateCreateInfo*		multisampleStateCreateInfo
1933 									&depthStencilStateCreateInfo);			// const VkPipelineDepthStencilStateCreateInfo*		depthStencilStateCreateInfo
1934 }
1935 
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const VkFormat depthStencilFormat)1936 Move<VkRenderPass> EarlyFragmentSampleCountTestInstance::makeRenderPass	(const DeviceInterface&	vk,
1937 																		 const VkDevice			device,
1938 																		 const VkFormat			colorFormat,
1939 																		 const VkFormat			depthStencilFormat)
1940 {
1941 	const VkAttachmentDescription			colorAttachmentDescription			=
1942 	{
1943 		(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags	flags;
1944 		colorFormat,								// VkFormat						format;
1945 		(VkSampleCountFlagBits)m_sampleCount,		// VkSampleCountFlagBits		samples;
1946 		VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp			loadOp;
1947 		VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp			storeOp;
1948 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp			stencilLoadOp
1949 		VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp			stencilStoreOp
1950 		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout				initialLayout
1951 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout				finalLayout
1952 	};
1953 
1954 	const VkAttachmentDescription			depthStencilAttachmentDescription	=
1955 	{
1956 		(VkAttachmentDescriptionFlags)0,					// VkStructureType			sType;
1957 		depthStencilFormat,									// VkFormat					format
1958 		(VkSampleCountFlagBits)m_sampleCount,				// VkSampleCountFlagBits	samples
1959 		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp		loadOp
1960 		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp		storeOp
1961 		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp		stencilLoadOp
1962 		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp		stencilStoreOp
1963 		VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			initialLayout
1964 		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL	// VkImageLayout			finalLayout
1965 	};
1966 
1967 	const VkAttachmentDescription			resolveAttachmentDescription		=
1968 	{
1969 
1970 		(VkAttachmentDescriptionFlags)0,			// VkSubpassDescriptionFlags	flags
1971 		colorFormat,								// VkFormat						format
1972 		VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits		samples
1973 		VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp			loadOp
1974 		VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp			storeOp
1975 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp			stencilLoadOp
1976 		VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp			stencilStoreOp
1977 		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout				initialLayout
1978 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout				finalLayout
1979 	};
1980 
1981 	std::vector<VkAttachmentDescription>	attachmentDescriptions;
1982 
1983 	attachmentDescriptions.push_back(colorAttachmentDescription);
1984 	attachmentDescriptions.push_back(depthStencilAttachmentDescription);
1985 	attachmentDescriptions.push_back(resolveAttachmentDescription);
1986 
1987 	const VkAttachmentReference				colorAttachmentRef					=
1988 	{
1989 		0u,											// deUint32			attachment
1990 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout	layout
1991 	};
1992 
1993 	const VkAttachmentReference				depthStencilAttachmentRef			=
1994 	{
1995 	    1u,													// deUint32			attachment
1996 		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout	layout
1997 	};
1998 
1999 	const VkAttachmentReference				resolveAttachmentRef				=
2000 	{
2001 		2u,											// deUint32			attachment
2002 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout	layout
2003 	};
2004 
2005 	const VkSubpassDescription				subpassDescription					=
2006 	{
2007 		(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags		flags
2008 		VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint				pipelineBindPoint
2009 		0u,									// deUint32							inputAttachmentCount
2010 		DE_NULL,							// const VkAttachmentReference2*	pInputAttachments
2011 		1u,									// deUint32							colorAttachmentCount
2012 		&colorAttachmentRef,				// const VkAttachmentReference2*	pColorAttachments
2013 		&resolveAttachmentRef,				// const VkAttachmentReference2*	pResolveAttachments
2014 		&depthStencilAttachmentRef,			// const VkAttachmentReference2*	pDepthStencilAttachment
2015 		0u,									// deUint32							preserveAttachmentCount
2016 		DE_NULL								// const deUint32*					pPreserveAttachments
2017 	};
2018 
2019 	const VkRenderPassCreateInfo			renderPassInfo						=
2020 	{
2021 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType					sType;
2022 		DE_NULL,									// const void*						pNext;
2023 		(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags;
2024 		(deUint32)attachmentDescriptions.size(),	// uint32_t							attachmentCount;
2025 		attachmentDescriptions.data(),				// const VkAttachmentDescription*	pAttachments;
2026 		1u,											// uint32_t							subpassCount;
2027 		&subpassDescription,						// const VkSubpassDescription*		pSubpasses;
2028 		0u,											// uint32_t							dependencyCount;
2029 		DE_NULL										// const VkSubpassDependency*		pDependencies;
2030 	};
2031 
2032 	return createRenderPass(vk, device, &renderPassInfo, DE_NULL);
2033 }
2034 
generateReferenceColorImage(const tcu::TextureFormat format,const tcu::IVec2 & renderSize)2035 tcu::TextureLevel EarlyFragmentSampleCountTestInstance::generateReferenceColorImage(const tcu::TextureFormat format, const tcu::IVec2 &renderSize)
2036 {
2037 	tcu::TextureLevel	image		(format, renderSize.x(), renderSize.y());
2038 	const tcu::Vec4		clearColor	= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
2039 
2040 	tcu::clear(image.getAccess(), clearColor);
2041 
2042 	return image;
2043 }
2044 
iterate(void)2045 tcu::TestStatus EarlyFragmentSampleCountTestInstance::iterate (void)
2046 {
2047 	const DeviceInterface&				vk							= m_context.getDeviceInterface();
2048 	const VkDevice						device						= m_context.getDevice();
2049 	const VkQueue						queue						= m_context.getUniversalQueue();
2050 	const deUint32						queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
2051 	Allocator&							allocator					= m_context.getDefaultAllocator();
2052 	const VkFormat						colorFormat					= VK_FORMAT_R8G8B8A8_UNORM;
2053 	const VkFormat						depthFormat					= VK_FORMAT_D16_UNORM;
2054 	VkQueryPool							queryPool;
2055 	const deUint32						queryCount					= 2u;
2056 	std::vector<VkDeviceSize>			sampleCounts				(queryCount);
2057 
2058 	// Create a query pool for storing the occlusion query result
2059 	{
2060 		VkQueryPoolCreateInfo			queryPoolInfo
2061 		{
2062 			VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,	// VkStructureType					sType;
2063 			DE_NULL,									// const void*						pNext;
2064 			(VkQueryPoolCreateFlags)0,					// VkQueryPoolCreateFlags			flags;
2065 			VK_QUERY_TYPE_OCCLUSION,					// VkQueryType						queryType;
2066 			queryCount,									// uint32_t							queryCount;
2067 			0u,											// VkQueryPipelineStatisticFlags	pipelineStatistics;
2068 		};
2069 
2070 		VK_CHECK(vk.createQueryPool(device, &queryPoolInfo, NULL, &queryPool));
2071 	}
2072 
2073 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth format " << getFormatName(VK_FORMAT_D16_UNORM) << tcu::TestLog::EndMessage;
2074 
2075 	// Color attachment
2076 	const tcu::IVec2					renderSize					= tcu::IVec2(32, 32);
2077 	const VkImageSubresourceRange		colorSubresourceRange		= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
2078 
2079 	const VkImageCreateInfo				imageParams =
2080 	{
2081 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,				// VkStructureType			sType;
2082 		DE_NULL,											// const void*				pNext;
2083 		(VkImageCreateFlags)0,								// VkImageCreateFlags		flags;
2084 		VK_IMAGE_TYPE_2D,									// VkImageType				imageType;
2085 		colorFormat,										// VkFormat					format;
2086 		makeExtent3D(renderSize.x(), renderSize.y(), 1),	// VkExtent3D				extent;
2087 		1u,													// deUint32					mipLevels;
2088 		1u,													// deUint32					arrayLayers;
2089 		(VkSampleCountFlagBits)m_sampleCount,				// VkSampleCountFlagBits	samples;
2090 		VK_IMAGE_TILING_OPTIMAL,							// VkImageTiling			tiling;
2091 		VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,				// VkImageUsageFlags		usage;
2092 		VK_SHARING_MODE_EXCLUSIVE,							// VkSharingMode			sharingMode;
2093 		0u,													// deUint32					queueFamilyIndexCount;
2094 		DE_NULL,											// const deUint32*			pQueueFamilyIndices;
2095 		VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			initialLayout;
2096 	};
2097 
2098 	const Unique<VkImage>				colorImage					(makeImage(vk, device, imageParams));
2099 	const UniquePtr<Allocation>			colorImageAlloc				(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
2100 	const Unique<VkImageView>			colorImageView				(makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
2101 
2102 	const Unique<VkImage>				resolveColorImage			(makeImage(vk, device, makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
2103 	const UniquePtr<Allocation>			resolveColorImageAlloc		(bindImage(vk, device, allocator, *resolveColorImage, MemoryRequirement::Any));
2104 	const Unique<VkImageView>			resolveColorImageView		(makeImageView(vk, device, *resolveColorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
2105 
2106 	// Depth-Stencil attachment
2107 	const VkImageSubresourceRange		depthSubresourceRange		= makeImageSubresourceRange(getImageAspectFlags(depthFormat), 0u, 1u, 0u, 1u);
2108 
2109 	const VkImageCreateInfo				depthImageParams			=
2110 	{
2111 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,				// VkStructureType			sType;
2112 		DE_NULL,											// const void*				pNext;
2113 		(VkImageCreateFlags)0,								// VkImageCreateFlags		flags;
2114 		VK_IMAGE_TYPE_2D,									// VkImageType				imageType;
2115 		depthFormat,										// VkFormat					format;
2116 		makeExtent3D(renderSize.x(), renderSize.y(), 1),	// VkExtent3D				extent;
2117 		1u,													// deUint32					mipLevels;
2118 		1u,													// deUint32					arrayLayers;
2119 		(VkSampleCountFlagBits)m_sampleCount,				// VkSampleCountFlagBits	samples;
2120 		VK_IMAGE_TILING_OPTIMAL,							// VkImageTiling			tiling;
2121 		VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,		// VkImageUsageFlags		usage;
2122 		VK_SHARING_MODE_EXCLUSIVE,							// VkSharingMode			sharingMode;
2123 		0u,													// deUint32					queueFamilyIndexCount;
2124 		DE_NULL,											// const deUint32*			pQueueFamilyIndices;
2125 		VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			initialLayout;
2126 	};
2127 
2128 	const Unique<VkImage>				depthImage					(makeImage(vk, device, depthImageParams));
2129 	const UniquePtr<Allocation>			depthImageAlloc				(bindImage(vk, device, allocator, *depthImage, MemoryRequirement::Any));
2130 	const Unique<VkImageView>			depthImageView				(makeImageView(vk, device, *depthImage, VK_IMAGE_VIEW_TYPE_2D, depthFormat, depthSubresourceRange));
2131 
2132 	const VkImageView					attachmentImages[]			= { *colorImageView, *depthImageView, *resolveColorImageView };
2133 	const deUint32						numUsedAttachmentImages		= DE_LENGTH_OF_ARRAY(attachmentImages);
2134 
2135 	// Vertex buffer
2136 	const deUint32						numVertices					= 6u;
2137 	const VkDeviceSize					vertexBufferSizeBytes		= 256 * numVertices;
2138 	const Unique<VkBuffer>				vertexBuffer				(makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
2139 	const UniquePtr<Allocation>			vertexBufferAlloc			(bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
2140 
2141 	{
2142 		tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
2143 
2144 		pVertices[0] = tcu::Vec4( 1.0f, -1.0f,  0.0f,  1.0f);
2145 		pVertices[1] = tcu::Vec4(-1.0f, -1.0f,  0.0f,  1.0f);
2146 		pVertices[2] = tcu::Vec4(-1.0f,  1.0f,  0.0f,  1.0f);
2147 
2148 		pVertices[3] = tcu::Vec4(-1.0f,  1.0f,  1.0f,  1.0f);
2149 		pVertices[4] = tcu::Vec4( 1.0f,  1.0f,  1.0f,  1.0f);
2150 		pVertices[5] = tcu::Vec4( 1.0f, -1.0f,  1.0f,  1.0f);
2151 
2152 		flushAlloc(vk, device, *vertexBufferAlloc);
2153 		// No barrier needed, flushed memory is automatically visible
2154 	}
2155 
2156 	// Render result buffer (to retrieve color attachment contents)
2157 
2158 	const VkDeviceSize					colorBufferSizeBytes		= tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
2159 	const Unique<VkBuffer>				colorBufferNoEarlyResults	(makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
2160 	const UniquePtr<Allocation>			colorBufferAllocNoEarly		(bindBuffer(vk, device, allocator, *colorBufferNoEarlyResults, MemoryRequirement::HostVisible));
2161 	const Unique<VkBuffer>				colorBufferEarlyResults		(makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
2162 	const UniquePtr<Allocation>			colorBufferAllocEarly		(bindBuffer(vk, device, allocator, *colorBufferEarlyResults, MemoryRequirement::HostVisible));
2163 
2164 	// Pipeline
2165 
2166 	const Unique<VkShaderModule>		vertexModule				(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
2167 	const Unique<VkShaderModule>		fragmentModuleNoEarly		(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
2168 	const Unique<VkShaderModule>		fragmentModuleEarlyFrag		(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag_early"), 0u));
2169 
2170 	const Unique<VkRenderPass>			renderPass					(makeRenderPass(vk, device, colorFormat, depthFormat));
2171 
2172 	const Unique<VkFramebuffer>			framebuffer					(makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages, renderSize.x(), renderSize.y()));
2173 
2174 	const Unique<VkPipelineLayout>		pipelineLayout				(makePipelineLayout(vk, device, DE_NULL));
2175 
2176 	// When we are creating a pipeline for runs without early fragment test, we are enabling all the samples for full coverage.
2177 	// Sample mask will be modified in a fragment shader.
2178 	const Unique<VkPipeline>			pipelineNoEarlyFrag			(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModuleNoEarly, renderSize, 0xFFFFFFFF));
2179 
2180 	// For early fragment tests, we are enabling only half of the samples.
2181 	const Unique<VkPipeline>			pipelineEarlyFrag			(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModuleEarlyFrag, renderSize, 0xAAAAAAAA));
2182 
2183 	// Build a command buffer
2184 
2185 	const Unique<VkCommandPool>			cmdPool						(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
2186 	const Unique<VkCommandBuffer>		cmdBuffer					(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2187 
2188 	enum QueryIndex
2189 	{
2190 		QUERY_INDEX_NO_EARLY_FRAG = 0,
2191 		QUERY_INDEX_EARLY_FRAG = 1
2192 	};
2193 
2194 	{
2195 		const VkRect2D					renderArea					=
2196 		{
2197 			makeOffset2D(0, 0),
2198 			makeExtent2D(renderSize.x(), renderSize.y()),
2199 		};
2200 
2201 		const tcu::Vec4					clearColor					(0.0f, 0.0f, 0.0f, 1.0f);
2202 		const VkDeviceSize				vertexBufferOffset			= 0ull;
2203 
2204 		beginCommandBuffer(vk, *cmdBuffer);
2205 
2206 		const VkClearValue				clearValues[]				=
2207 		{
2208 			makeClearValueColor(clearColor),		// attachment 0
2209 			makeClearValueDepthStencil(0.5f, 3u),	// attachment 1
2210 			makeClearValueColor(clearColor),		// attachment 2
2211 			makeClearValueDepthStencil(0.5f, 3u),	// attachment 3
2212 		};
2213 
2214 		const VkRenderPassBeginInfo		renderPassBeginInfo			=
2215 		{
2216 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,	// VkStructureType		sType;
2217 			DE_NULL,									// const void*			pNext;
2218 			*renderPass,								// VkRenderPass			renderPass;
2219 			*framebuffer,								// VkFramebuffer		framebuffer;
2220 			renderArea,									// VkRect2D				renderArea;
2221 			DE_LENGTH_OF_ARRAY(clearValues),			// deUint32				clearValueCount;
2222 			clearValues,								// const VkClearValue*	pClearValues;
2223 		};
2224 
2225 		// Reset query pool. Must be done outside of render pass
2226 		vk.cmdResetQueryPool(*cmdBuffer, queryPool, 0, queryCount);
2227 
2228 		vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
2229 
2230 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
2231 
2232 		// Run without early fragment test.
2233 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineNoEarlyFrag);
2234 
2235 		vk.cmdBeginQuery(cmdBuffer.get(), queryPool, QUERY_INDEX_NO_EARLY_FRAG, VK_QUERY_CONTROL_PRECISE_BIT);
2236 		vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
2237 		vk.cmdEndQuery(cmdBuffer.get(), queryPool, QUERY_INDEX_NO_EARLY_FRAG);
2238 
2239 		endRenderPass(vk, *cmdBuffer);
2240 
2241 		copyImageToBuffer(vk, *cmdBuffer, *resolveColorImage, *colorBufferNoEarlyResults, renderSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
2242 
2243 		vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
2244 
2245 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
2246 
2247 		// Run with early fragment test.
2248 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineEarlyFrag);
2249 
2250 		vk.cmdBeginQuery(cmdBuffer.get(), queryPool, QUERY_INDEX_EARLY_FRAG, VK_QUERY_CONTROL_PRECISE_BIT);
2251 		vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
2252 		vk.cmdEndQuery(cmdBuffer.get(), queryPool, QUERY_INDEX_EARLY_FRAG);
2253 
2254 		endRenderPass(vk, *cmdBuffer);
2255 
2256 		copyImageToBuffer(vk, *cmdBuffer, *resolveColorImage, *colorBufferEarlyResults, renderSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
2257 
2258 		endCommandBuffer(vk, *cmdBuffer);
2259 		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
2260 	}
2261 
2262 	// When early fragment test is enabled, all samples are killed in fragment shader. The result color should be black.
2263 	{
2264 		invalidateAlloc(vk, device, *colorBufferAllocEarly);
2265 
2266 		const tcu::ConstPixelBufferAccess	imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAllocEarly->getHostPtr());
2267 		const tcu::TextureLevel				referenceImage = generateReferenceColorImage(mapVkFormat(colorFormat), renderSize);
2268 
2269 		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))
2270 			return tcu::TestStatus::fail("Rendered color image is not correct");
2271 	}
2272 
2273 	// The image has 32x32 pixels and each pixel has m_sampleCount samples. Half of these samples are discarded before sample counting.
2274 	// This means the reference value for passed samples is ((32 x 32) / 2 / 2) * sampleCount.
2275 	{
2276 		deUint64	refValue	= deUint64(deUint32((renderSize.x() * renderSize.y()) / 4) * m_sampleCount);
2277 		deUint64	tolerance	= deUint64(refValue * 5 / 100);
2278 		deUint64	minValue	= refValue - tolerance;
2279 		deUint64	maxValue	= refValue + tolerance;
2280 
2281 		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));
2282 
2283 		// Log test results
2284 		{
2285 			tcu::TestLog& log = m_context.getTestContext().getLog();
2286 
2287 			log << tcu::TestLog::Message << "\nAcceptable range: " << minValue << " - " << maxValue << tcu::TestLog::EndMessage;
2288 			log << tcu::TestLog::Message << "Passed Samples (without early fragment test) : " << de::toString(sampleCounts[0]) << tcu::TestLog::EndMessage;
2289 			log << tcu::TestLog::Message << "Passed Samples (with early fragment test)    : " << de::toString(sampleCounts[1]) << tcu::TestLog::EndMessage;
2290 		}
2291 
2292 #ifndef CTS_USES_VULKANSC
2293 		vk.destroyQueryPool(device, queryPool, nullptr);
2294 #endif // CTS_USES_VULKANSC
2295 
2296 		// Check that number of the all passed samples are within an acceptable range.
2297 		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)
2298 		{
2299 			return tcu::TestStatus::pass("Success");
2300 		}
2301 		else if (sampleCounts[QUERY_INDEX_NO_EARLY_FRAG] >= minValue && sampleCounts[QUERY_INDEX_NO_EARLY_FRAG] <= maxValue && sampleCounts[QUERY_INDEX_EARLY_FRAG] == 0)
2302 		{
2303 			// Spec says: "If the fragment shader declares the EarlyFragmentTests execution mode, fragment shading and
2304 			// multisample coverage operations should instead be performed after sample counting.
2305 
2306 			// since the specification says 'should', the opposite behavior is allowed, but not preferred
2307 			return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Sample count is 0 - sample counting performed after multisample coverage and fragment shading");
2308 		}
2309 		else if (sampleCounts[QUERY_INDEX_NO_EARLY_FRAG] >= minValue && sampleCounts[QUERY_INDEX_NO_EARLY_FRAG] <= maxValue &&
2310 					sampleCounts[QUERY_INDEX_EARLY_FRAG] >= (minValue * 2) && sampleCounts[QUERY_INDEX_EARLY_FRAG] <= (maxValue * 2))
2311 		{
2312 			// If the sample count returned is double the expected value, the sample mask test has been executed after
2313 			// sample counting.
2314 
2315 			// Spec says: "If there is a fragment shader and it declares the EarlyFragmentTests execution mode, ...
2316 			// sample mask test may: instead be performed after sample counting"
2317 
2318 			// since the specification says 'may', the opposite behavior is allowed, but not preferred
2319 			return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Sample count is greater than expected - sample mask test performed after sample counting");
2320 		}
2321 		else
2322 		{
2323 			// Log no early frag test images
2324 			{
2325 				tcu::TestLog& log = m_context.getTestContext().getLog();
2326 
2327 				invalidateAlloc(vk, device, *colorBufferAllocNoEarly);
2328 
2329 				const tcu::ConstPixelBufferAccess	imagePixelAccess	(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAllocNoEarly->getHostPtr());
2330 
2331 				log << tcu::LogImageSet("No Early Frag Test Images", "No Early Fragment Test Images")
2332 					<< tcu::TestLog::Image("color", "Rendered image (color)", imagePixelAccess)
2333 					<< tcu::TestLog::EndImageSet;
2334 			}
2335 
2336 			// Log early frag test images
2337 			{
2338 				tcu::TestLog& log = m_context.getTestContext().getLog();
2339 
2340 				invalidateAlloc(vk, device, *colorBufferAllocEarly);
2341 
2342 				const tcu::ConstPixelBufferAccess	imagePixelAccess	(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAllocEarly->getHostPtr());
2343 
2344 				log << tcu::LogImageSet("Early Frag Test Images", "Early Fragment Test Images")
2345 					<< tcu::TestLog::Image("color", "Rendered image (color)", imagePixelAccess)
2346 					<< tcu::TestLog::EndImageSet;
2347 			}
2348 
2349 			return tcu::TestStatus::fail("Sample count value outside expected range.");
2350 		}
2351 	}
2352 }
2353 
2354 class EarlyFragmentSampleCountTest : public EarlyFragmentTest
2355 {
2356 public:
2357 	EarlyFragmentSampleCountTest		(tcu::TestContext&	testCtx,
2358 										 const std::string	name,
2359 										 const deUint32		sampleCount,
2360 										 const bool			earlyAndLate);
2361 
2362 	void				initPrograms	(SourceCollections& programCollection) const override;
2363 	TestInstance*		createInstance	(Context& context) const override;
2364 	void				checkSupport	(Context& context) const override;
2365 
2366 private:
2367 	const deUint32		m_sampleCount;
2368 	const bool			m_earlyAndLate;
2369 };
2370 
EarlyFragmentSampleCountTest(tcu::TestContext & testCtx,const std::string name,const deUint32 sampleCount,const bool earlyAndLate)2371 EarlyFragmentSampleCountTest::EarlyFragmentSampleCountTest(tcu::TestContext& testCtx, const std::string name, const deUint32 sampleCount, const bool earlyAndLate)
2372 	: EarlyFragmentTest	(testCtx, name, FLAG_TEST_DEPTH)
2373 	, m_sampleCount		(sampleCount)
2374 	, m_earlyAndLate	(earlyAndLate)
2375 {
2376 }
2377 
createInstance(Context & context) const2378 TestInstance* EarlyFragmentSampleCountTest::createInstance (Context& context) const
2379 {
2380 	return new EarlyFragmentSampleCountTestInstance(context, m_sampleCount);
2381 }
2382 
initPrograms(SourceCollections & programCollection) const2383 void EarlyFragmentSampleCountTest::initPrograms(SourceCollections& programCollection) const
2384 {
2385 	// Vertex shader
2386 	{
2387 		std::ostringstream vrt;
2388 
2389 		vrt << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2390 			<< "\n"
2391 			<< "layout(location = 0) in highp vec4 position;\n"
2392 			<< "\n"
2393 			<< "out gl_PerVertex {\n"
2394 			<< "   vec4 gl_Position;\n"
2395 			<< "};\n"
2396 			<< "\n"
2397 			<< "void main (void)\n"
2398 			<< "{\n"
2399 			<< "    gl_Position = position;\n"
2400 			<< "}\n";
2401 
2402 		programCollection.glslSources.add("vert") << glu::VertexSource(vrt.str());
2403 	}
2404 
2405 	// Fragment shader for runs without early fragment test
2406 	if (m_earlyAndLate == false)
2407 	{
2408 		std::ostringstream frg;
2409 
2410 		frg << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2411 			<< "\n"
2412 			<< "layout(location = 0) out highp vec4 fragColor;\n"
2413 			<< "\n"
2414 			<< "void main (void)\n"
2415 			<< "{\n"
2416 			<< "    // This will kill half of the samples.\n"
2417 			<< "    gl_SampleMask[0] = 0xAAAAAAAA;\n"
2418 			<< "    fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
2419 			<< "}\n";
2420 
2421 		programCollection.glslSources.add("frag") << glu::FragmentSource(frg.str());
2422 	}
2423 	else
2424 	{
2425 		const SpirVAsmBuildOptions	buildOptionsSpr(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3);
2426 		const std::string			src =
2427 			"; SPIR - V\n"
2428 			"; Version: 1.0\n"
2429 			"; Generator: Khronos Glslang Reference Front End; 10\n"
2430 			"; Bound: 23\n"
2431 			"; Schema: 0\n"
2432 			"OpCapability Shader\n"
2433 			"OpExtension \"SPV_AMD_shader_early_and_late_fragment_tests\"\n"
2434 			"%1 = OpExtInstImport \"GLSL.std.450\"\n"
2435 			"OpMemoryModel Logical GLSL450\n"
2436 			"OpEntryPoint Fragment %4 \"main\" %11 %19\n"
2437 			"OpExecutionMode %4 OriginUpperLeft\n"
2438 			"OpExecutionMode %4 EarlyAndLateFragmentTestsAMD\n"
2439 			"OpExecutionMode %4 DepthReplacing\n"
2440 			"OpExecutionMode %4 DepthLess\n"
2441 			"OpDecorate %11 BuiltIn SampleMask\n"
2442 			"OpDecorate %19 Location 0\n"
2443 			"%2 = OpTypeVoid\n"
2444 			"%3 = OpTypeFunction %2\n"
2445 			"%6 = OpTypeInt 32 1\n"
2446 			"%7 = OpTypeInt 32 0\n"
2447 			"%8 = OpConstant %7 1\n"
2448 			"%9 = OpTypeArray %6 %8\n"
2449 			"%10 = OpTypePointer Output %9\n"
2450 			"%11 = OpVariable %10 Output\n"
2451 			"%12 = OpConstant %6 0\n"
2452 			"%13 = OpConstant %6 -1431655766\n"
2453 			"%14 = OpTypePointer Output %6\n"
2454 			"%16 = OpTypeFloat 32\n"
2455 			"%17 = OpTypeVector %16 4\n"
2456 			"%18 = OpTypePointer Output %17\n"
2457 			"%19 = OpVariable %18 Output\n"
2458 			"%20 = OpConstant %16 1\n"
2459 			"%21 = OpConstant %16 0\n"
2460 			"%22 = OpConstantComposite %17 %20 %20 %21 %20\n"
2461 			"%4 = OpFunction %2 None %3\n"
2462 			"%5 = OpLabel\n"
2463 			"%15 = OpAccessChain %14 %11 %12\n"
2464 			"OpStore %15 %13\n"
2465 			"OpStore %19 %22\n"
2466 			"OpReturn\n"
2467 			"OpFunctionEnd\n";
2468 		programCollection.spirvAsmSources.add("frag") << src << buildOptionsSpr;
2469 	}
2470 
2471 	// Fragment shader for early fragment tests
2472 	if (m_earlyAndLate == false)
2473 	{
2474 		std::ostringstream frg;
2475 
2476 		frg << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2477 			<< "\n"
2478 			<< "layout(early_fragment_tests) in;\n"
2479 			<< "\n"
2480 			<< "layout(location = 0) out highp vec4 fragColor;\n"
2481 			<< "\n"
2482 			<< "void main (void)\n"
2483 			<< "{\n"
2484 			<< "    // Sample mask kills all the samples, but the sample counting has already happened.\n"
2485 			<< "    gl_SampleMask[0] = 0x0;\n"
2486 			<< "    fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
2487 			<< "}\n";
2488 
2489 		programCollection.glslSources.add("frag_early") << glu::FragmentSource(frg.str());
2490 	}
2491 	else
2492 	{
2493 		const SpirVAsmBuildOptions	buildOptionsSpr(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3);
2494 		const std::string			src	=
2495 			"; SPIR - V\n"
2496 			"; Version: 1.0\n"
2497 			"; Generator: Khronos Glslang Reference Front End; 10\n"
2498 			"; Bound: 22\n"
2499 			"; Schema: 0\n"
2500 			"OpCapability Shader\n"
2501 			"OpExtension \"SPV_AMD_shader_early_and_late_fragment_tests\"\n"
2502 			"%1 = OpExtInstImport \"GLSL.std.450\"\n"
2503 			"OpMemoryModel Logical GLSL450\n"
2504 			"OpEntryPoint Fragment %4 \"main\" %11 %18\n"
2505 			"OpExecutionMode %4 OriginUpperLeft\n"
2506 			"OpExecutionMode %4 EarlyAndLateFragmentTestsAMD\n"
2507 			"OpDecorate %11 BuiltIn SampleMask\n"
2508 			"OpDecorate %18 Location 0\n"
2509 			"%2 = OpTypeVoid\n"
2510 			"%3 = OpTypeFunction %2\n"
2511 			"%6 = OpTypeInt 32 1\n"
2512 			"%7 = OpTypeInt 32 0\n"
2513 			"%8 = OpConstant %7 1\n"
2514 			"%9 = OpTypeArray %6 %8\n"
2515 			"%10 = OpTypePointer Output %9\n"
2516 			"%11 = OpVariable %10 Output\n"
2517 			"%12 = OpConstant %6 0\n"
2518 			"%13 = OpTypePointer Output %6\n"
2519 			"%15 = OpTypeFloat 32\n"
2520 			"%16 = OpTypeVector %15 4\n"
2521 			"%17 = OpTypePointer Output %16\n"
2522 			"%18 = OpVariable %17 Output\n"
2523 			"%19 = OpConstant %15 1\n"
2524 			"%20 = OpConstant %15 0\n"
2525 			"%21 = OpConstantComposite %16 %19 %19 %20 %19\n"
2526 			"%4 = OpFunction %2 None %3\n"
2527 			"%5 = OpLabel\n"
2528 			"%14 = OpAccessChain %13 %11 %12\n"
2529 			"OpStore %14 %12\n"
2530 			"OpStore %18 %21\n"
2531 			"OpReturn\n"
2532 			"OpFunctionEnd\n";
2533 		programCollection.spirvAsmSources.add("frag_early") << src << buildOptionsSpr;
2534 	}
2535 }
2536 
checkSupport(Context & context) const2537 void EarlyFragmentSampleCountTest::checkSupport(Context& context) const
2538 {
2539 	EarlyFragmentTest::checkSupport(context);
2540 
2541 	// Check support for MSAA image formats used in the test.
2542 	const InstanceInterface&	vki				= context.getInstanceInterface();
2543 	const VkPhysicalDevice		physDevice		= context.getPhysicalDevice();
2544 	const VkFormat				colorFormat		= VK_FORMAT_R8G8B8A8_UNORM;
2545 	const VkFormat				depthFormat		= VK_FORMAT_D16_UNORM;
2546 
2547 	VkImageFormatProperties		formatProperties;
2548 
2549 	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);
2550 	if ((formatProperties.sampleCounts & m_sampleCount) == 0)
2551 		TCU_THROW(NotSupportedError, "Format does not support this number of samples for color format");
2552 
2553 	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);
2554 	if ((formatProperties.sampleCounts & m_sampleCount) == 0)
2555 		TCU_THROW(NotSupportedError, "Format does not support this number of samples for depth format");
2556 
2557 #ifndef CTS_USES_VULKANSC
2558 	if (m_earlyAndLate)
2559 	{
2560 		context.requireDeviceFunctionality("VK_AMD_shader_early_and_late_fragment_tests");
2561 		if (context.getShaderEarlyAndLateFragmentTestsFeaturesAMD().shaderEarlyAndLateFragmentTests == VK_FALSE)
2562 			TCU_THROW(NotSupportedError, "shaderEarlyAndLateFragmentTests is not supported");
2563 	}
2564 #endif
2565 }
2566 
2567 } // anonymous ns
2568 
createEarlyFragmentTests(tcu::TestContext & testCtx)2569 tcu::TestCaseGroup* createEarlyFragmentTests (tcu::TestContext& testCtx)
2570 {
2571 	de::MovePtr<tcu::TestCaseGroup> testGroup			(new tcu::TestCaseGroup(testCtx, "early_fragment", "early fragment test cases"));
2572 
2573 	{
2574 		struct TestCaseEarly
2575 		{
2576 			std::string caseName;
2577 			deUint32	flags;
2578 		};
2579 
2580 		static const TestCaseEarly cases[] =
2581 		{
2582 
2583 			{ "no_early_fragment_tests_depth",					FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS									},
2584 			{ "no_early_fragment_tests_stencil",				FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS									},
2585 			{ "early_fragment_tests_depth",						FLAG_TEST_DEPTH																			},
2586 			{ "early_fragment_tests_stencil",					FLAG_TEST_STENCIL																		},
2587 			{ "no_early_fragment_tests_depth_no_attachment",	FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT	},
2588 			{ "no_early_fragment_tests_stencil_no_attachment",	FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT	},
2589 			{ "early_fragment_tests_depth_no_attachment",		FLAG_TEST_DEPTH   | FLAG_DONT_USE_TEST_ATTACHMENT										},
2590 			{ "early_fragment_tests_stencil_no_attachment",		FLAG_TEST_STENCIL | FLAG_DONT_USE_TEST_ATTACHMENT										},
2591 		};
2592 
2593 #ifndef CTS_USES_VULKANSC
2594 		static const TestCaseEarly casesEarlyAndLate[] =
2595 		{
2596 			{ "early_and_late_fragment_tests_depth",				FLAG_TEST_DEPTH   | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS									},
2597 			{ "early_and_late_fragment_tests_stencil",				FLAG_TEST_STENCIL | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS									},
2598 			{ "early_and_late_fragment_tests_depth_no_attachment",	FLAG_TEST_DEPTH   | FLAG_DONT_USE_TEST_ATTACHMENT | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS	},
2599 			{ "early_and_late_fragment_tests_stencil_no_attachment",FLAG_TEST_STENCIL | FLAG_DONT_USE_TEST_ATTACHMENT | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS	},
2600 		};
2601 #endif
2602 
2603 		for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
2604 			testGroup->addChild(new EarlyFragmentTest(testCtx, cases[i].caseName, cases[i].flags));
2605 #ifndef CTS_USES_VULKANSC
2606 		for (int i = 0; i < DE_LENGTH_OF_ARRAY(casesEarlyAndLate); ++i)
2607 			testGroup->addChild(new EarlyFragmentTest(testCtx, casesEarlyAndLate[i].caseName, casesEarlyAndLate[i].flags));
2608 #endif
2609 	}
2610 
2611 	// Check that discard does not affect depth test writes.
2612 	{
2613 		static const struct
2614 		{
2615 			std::string caseName;
2616 			deUint32	flags;
2617 		} cases[] =
2618 		{
2619 			{ "discard_no_early_fragment_tests_depth",			FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS										},
2620 			{ "discard_no_early_fragment_tests_stencil",		FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS										},
2621 			{ "discard_early_fragment_tests_depth",				FLAG_TEST_DEPTH																				},
2622 			{ "discard_early_fragment_tests_stencil",			FLAG_TEST_STENCIL																			},
2623 #ifndef CTS_USES_VULKANSC
2624 			{ "discard_early_and_late_fragment_tests_depth",	FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS	},
2625 			{ "discard_early_and_late_fragment_tests_stencil",	FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS	},
2626 #endif
2627 		};
2628 
2629 		for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
2630 			testGroup->addChild(new EarlyFragmentDiscardTest(testCtx, cases[i].caseName, cases[i].flags));
2631 	}
2632 
2633 	// Check that writing to gl_SampleMask does not affect depth test writes.
2634 	{
2635 		static const struct
2636 		{
2637 			std::string caseName;
2638 			deUint32	flags;
2639 		} cases[] =
2640 		{
2641 			{ "samplemask_no_early_fragment_tests_depth",						FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS										},
2642 			{ "samplemask_early_fragment_tests_depth",							FLAG_TEST_DEPTH																				},
2643 #ifndef CTS_USES_VULKANSC
2644 			{ "samplemask_early_and_late_fragment_tests_depth_replacing_mode",	FLAG_TEST_DEPTH | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS	},
2645 			{ "samplemask_early_and_late_fragment_tests_depth",					FLAG_TEST_DEPTH | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS										},
2646 #endif
2647 		};
2648 
2649 		const VkSampleCountFlags sampleCounts[] = { VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT, VK_SAMPLE_COUNT_16_BIT };
2650 		const std::string sampleCountsStr[] = { "samples_2", "samples_4", "samples_8", "samples_16" };
2651 
2652 		for (deUint32 sampleCountsNdx = 0; sampleCountsNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountsNdx++)
2653 		{
2654 			for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
2655 				testGroup->addChild(new EarlyFragmentSampleMaskTest(testCtx, cases[i].caseName + "_" + sampleCountsStr[sampleCountsNdx], cases[i].flags, sampleCounts[sampleCountsNdx]));
2656 		}
2657 	}
2658 
2659 	// 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.
2660 	{
2661 		const VkSampleCountFlags	sampleCounts[]		= { VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT, VK_SAMPLE_COUNT_16_BIT };
2662 		const std::string			sampleCountsStr[]	= { "samples_2", "samples_4", "samples_8", "samples_16" };
2663 
2664 		for (deUint32 sampleCountsNdx = 0; sampleCountsNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountsNdx++)
2665 		{
2666 			testGroup->addChild(new EarlyFragmentSampleCountTest(testCtx, "sample_count_early_fragment_tests_depth_" + sampleCountsStr[sampleCountsNdx], sampleCounts[sampleCountsNdx], false));
2667 #ifndef CTS_USES_VULKANSC
2668 			testGroup->addChild(new EarlyFragmentSampleCountTest(testCtx, "sample_count_early_and_late_fragment_tests_depth_" + sampleCountsStr[sampleCountsNdx], sampleCounts[sampleCountsNdx], true));
2669 #endif
2670 		}
2671 	}
2672 
2673 	return testGroup.release();
2674 }
2675 
2676 } // FragmentOperations
2677 } // vkt
2678