• 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 "vktFragmentOperationsMakeUtil.hpp"
27 #include "vktTestCaseUtil.hpp"
28 
29 #include "vkDefs.hpp"
30 #include "vkRef.hpp"
31 #include "vkRefUtil.hpp"
32 #include "vkPlatform.hpp"
33 #include "vkPrograms.hpp"
34 #include "vkMemUtil.hpp"
35 #include "vkBuilderUtil.hpp"
36 #include "vkStrUtil.hpp"
37 #include "vkTypeUtil.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "vkImageUtil.hpp"
40 #include "vkBarrierUtil.hpp"
41 #include "vkCmdUtil.hpp"
42 #include "vkObjUtil.hpp"
43 
44 #include "tcuTestLog.hpp"
45 #include "tcuImageCompare.hpp"
46 #include "tcuTextureUtil.hpp"
47 
48 #include "deUniquePtr.hpp"
49 #include "deStringUtil.hpp"
50 #include "deMath.h"
51 
52 #include <string>
53 
54 namespace vkt
55 {
56 namespace FragmentOperations
57 {
58 namespace
59 {
60 using namespace vk;
61 using de::UniquePtr;
62 
63 //! Basic 2D image.
makeImageCreateInfo(const tcu::IVec2 & size,const VkFormat format,const VkImageUsageFlags usage)64 inline VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage)
65 {
66 	const VkImageCreateInfo imageParams =
67 	{
68 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,					// VkStructureType			sType;
69 		DE_NULL,												// const void*				pNext;
70 		(VkImageCreateFlags)0,									// VkImageCreateFlags		flags;
71 		VK_IMAGE_TYPE_2D,										// VkImageType				imageType;
72 		format,													// VkFormat					format;
73 		makeExtent3D(size.x(), size.y(), 1),					// VkExtent3D				extent;
74 		1u,														// deUint32					mipLevels;
75 		1u,														// deUint32					arrayLayers;
76 		VK_SAMPLE_COUNT_1_BIT,									// VkSampleCountFlagBits	samples;
77 		VK_IMAGE_TILING_OPTIMAL,								// VkImageTiling			tiling;
78 		usage,													// VkImageUsageFlags		usage;
79 		VK_SHARING_MODE_EXCLUSIVE,								// VkSharingMode			sharingMode;
80 		0u,														// deUint32					queueFamilyIndexCount;
81 		DE_NULL,												// const deUint32*			pQueueFamilyIndices;
82 		VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout			initialLayout;
83 	};
84 	return imageParams;
85 }
86 
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const bool useDepthStencilAttachment,const VkFormat depthStencilFormat)87 Move<VkRenderPass> makeRenderPass (const DeviceInterface&	vk,
88 								   const VkDevice			device,
89 								   const VkFormat			colorFormat,
90 								   const bool				useDepthStencilAttachment,
91 								   const VkFormat			depthStencilFormat)
92 {
93 	return makeRenderPass(vk, device, colorFormat, useDepthStencilAttachment ? depthStencilFormat : VK_FORMAT_UNDEFINED);
94 }
95 
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)96 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&	vk,
97 									   const VkDevice			device,
98 									   const VkPipelineLayout	pipelineLayout,
99 									   const VkRenderPass		renderPass,
100 									   const VkShaderModule		vertexModule,
101 									   const VkShaderModule		fragmentModule,
102 									   const tcu::IVec2&		renderSize,
103 									   const bool				enableDepthTest,
104 									   const bool				enableStencilTest,
105 									   const VkStencilOp		stencilFailOp = VK_STENCIL_OP_KEEP,
106 									   const VkStencilOp		stencilPassOp = VK_STENCIL_OP_KEEP)
107 {
108 	const std::vector<VkViewport>			viewports					(1, makeViewport(renderSize));
109 	const std::vector<VkRect2D>				scissors					(1, makeRect2D(renderSize));
110 
111 	const VkStencilOpState					stencilOpState				= makeStencilOpState(
112 		stencilFailOp,			// stencil fail
113 	    stencilPassOp,			// depth & stencil pass
114 		VK_STENCIL_OP_KEEP,		// depth only fail
115 		VK_COMPARE_OP_EQUAL,	// compare op
116 		0x3,					// compare mask
117 		0xf,					// write mask
118 		1u);					// reference
119 
120 	VkPipelineDepthStencilStateCreateInfo	depthStencilStateCreateInfo	=
121 	{
122 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType                          sType
123 		DE_NULL,													// const void*                              pNext
124 		0u,															// VkPipelineDepthStencilStateCreateFlags   flags
125 		enableDepthTest ? VK_TRUE : VK_FALSE,						// VkBool32                                 depthTestEnable
126 		enableDepthTest ? VK_TRUE : VK_FALSE,						// VkBool32                                 depthWriteEnable
127 		VK_COMPARE_OP_LESS,											// VkCompareOp                              depthCompareOp
128 		VK_FALSE,													// VkBool32                                 depthBoundsTestEnable
129 		enableStencilTest ? VK_TRUE : VK_FALSE,						// VkBool32                                 stencilTestEnable
130 		stencilOpState,												// VkStencilOpState                         front
131 		stencilOpState,												// VkStencilOpState                         back
132 		0.0f,														// float                                    minDepthBounds
133 		1.0f														// float                                    maxDepthBounds
134 	};
135 
136 	return vk::makeGraphicsPipeline(vk,										// const DeviceInterface&                        vk
137 									device,									// const VkDevice                                device
138 									pipelineLayout,							// const VkPipelineLayout                        pipelineLayout
139 									vertexModule,							// const VkShaderModule                          vertexShaderModule
140 									DE_NULL,								// const VkShaderModule                          tessellationControlModule
141 									DE_NULL,								// const VkShaderModule                          tessellationEvalModule
142 									DE_NULL,								// const VkShaderModule                          geometryShaderModule
143 									fragmentModule,							// const VkShaderModule                          fragmentShaderModule
144 									renderPass,								// const VkRenderPass                            renderPass
145 									viewports,								// const std::vector<VkViewport>&                viewports
146 									scissors,								// const std::vector<VkRect2D>&                  scissors
147 									VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology                     topology
148 									0u,										// const deUint32                                subpass
149 									0u,										// const deUint32                                patchControlPoints
150 									DE_NULL,								// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
151 									DE_NULL,								// const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
152 									DE_NULL,								// const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
153 									&depthStencilStateCreateInfo);			// const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
154 }
155 
commandClearStencilAttachment(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const VkOffset2D & offset,const VkExtent2D & extent,const deUint32 clearValue)156 void commandClearStencilAttachment (const DeviceInterface&	vk,
157 									const VkCommandBuffer	commandBuffer,
158 									const VkOffset2D&		offset,
159 									const VkExtent2D&		extent,
160 									const deUint32			clearValue)
161 {
162 	const VkClearAttachment stencilAttachment =
163 	{
164 		VK_IMAGE_ASPECT_STENCIL_BIT,					// VkImageAspectFlags    aspectMask;
165 		0u,												// uint32_t              colorAttachment;
166 		makeClearValueDepthStencil(0.0f, clearValue),	// VkClearValue          clearValue;
167 	};
168 
169 	const VkClearRect rect =
170 	{
171 		{ offset, extent },		// VkRect2D    rect;
172 		0u,						// uint32_t    baseArrayLayer;
173 		1u,						// uint32_t    layerCount;
174 	};
175 
176 	vk.cmdClearAttachments(commandBuffer, 1u, &stencilAttachment, 1u, &rect);
177 }
178 
getImageAspectFlags(const VkFormat format)179 VkImageAspectFlags getImageAspectFlags (const VkFormat format)
180 {
181 	const tcu::TextureFormat tcuFormat = mapVkFormat(format);
182 
183 	if      (tcuFormat.order == tcu::TextureFormat::DS)		return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
184 	else if (tcuFormat.order == tcu::TextureFormat::D)		return VK_IMAGE_ASPECT_DEPTH_BIT;
185 	else if (tcuFormat.order == tcu::TextureFormat::S)		return VK_IMAGE_ASPECT_STENCIL_BIT;
186 
187 	DE_ASSERT(false);
188 	return 0u;
189 }
190 
isSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,const VkPhysicalDevice device,const VkFormat format)191 bool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, const VkPhysicalDevice device, const VkFormat format)
192 {
193 	VkFormatProperties formatProps;
194 	instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
195 	return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
196 }
197 
pickSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,const VkPhysicalDevice device,const deUint32 numFormats,const VkFormat * pFormats)198 VkFormat pickSupportedDepthStencilFormat (const InstanceInterface&	instanceInterface,
199 										  const VkPhysicalDevice	device,
200 										  const deUint32			numFormats,
201 										  const VkFormat*			pFormats)
202 {
203 	for (deUint32 i = 0; i < numFormats; ++i)
204 		if (isSupportedDepthStencilFormat(instanceInterface, device, pFormats[i]))
205 			return pFormats[i];
206 	return VK_FORMAT_UNDEFINED;
207 }
208 
209 enum Flags
210 {
211 	FLAG_TEST_DEPTH							= 1u << 0,
212 	FLAG_TEST_STENCIL						= 1u << 1,
213 	FLAG_DONT_USE_TEST_ATTACHMENT			= 1u << 2,
214 	FLAG_DONT_USE_EARLY_FRAGMENT_TESTS		= 1u << 3,
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 	{
261 		const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0;
262 		std::ostringstream src;
263 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
264 			<< "\n"
265 			<< (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "")
266 			<< "layout(location = 0) out highp vec4 fragColor;\n"
267 			<< "\n"
268 			<< "layout(binding = 0) coherent buffer Output {\n"
269 			<< "    uint result;\n"
270 			<< "} sb_out;\n"
271 			<< "\n"
272 			<< "void main (void)\n"
273 			<< "{\n"
274 			<< "    atomicAdd(sb_out.result, 1u);\n"
275 			<< "	fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
276 			<< "}\n";
277 
278 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
279 	}
280 }
281 
282 class EarlyFragmentTestInstance : public TestInstance
283 {
284 public:
285 							EarlyFragmentTestInstance (Context& context, const deUint32 flags);
286 
287 	tcu::TestStatus			iterate					  (void);
288 
289 private:
290 	enum TestMode
291 	{
292 		MODE_INVALID,
293 		MODE_DEPTH,
294 		MODE_STENCIL,
295 	};
296 
297 	const TestMode			m_testMode;
298 	const bool				m_useTestAttachment;
299 	const bool				m_useEarlyTests;
300 };
301 
EarlyFragmentTestInstance(Context & context,const deUint32 flags)302 EarlyFragmentTestInstance::EarlyFragmentTestInstance (Context& context, const deUint32 flags)
303 	: TestInstance			(context)
304 	, m_testMode			(flags & FLAG_TEST_DEPTH   ? MODE_DEPTH :
305 							 flags & FLAG_TEST_STENCIL ? MODE_STENCIL : MODE_INVALID)
306 	, m_useTestAttachment	((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0)
307 	, m_useEarlyTests		((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0)
308 {
309 	DE_ASSERT(m_testMode != MODE_INVALID);
310 }
311 
iterate(void)312 tcu::TestStatus EarlyFragmentTestInstance::iterate (void)
313 {
314 	const DeviceInterface&		vk					= m_context.getDeviceInterface();
315 	const InstanceInterface&	vki					= m_context.getInstanceInterface();
316 	const VkDevice				device				= m_context.getDevice();
317 	const VkPhysicalDevice		physDevice			= m_context.getPhysicalDevice();
318 	const VkQueue				queue				= m_context.getUniversalQueue();
319 	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
320 	Allocator&					allocator			= m_context.getDefaultAllocator();
321 
322 	// Color attachment
323 
324 	const tcu::IVec2				renderSize			= tcu::IVec2(32, 32);
325 	const VkFormat					colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
326 	const VkImageSubresourceRange	colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
327 	const Unique<VkImage>			colorImage			(makeImage(vk, device, makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
328 	const UniquePtr<Allocation>		colorImageAlloc		(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
329 	const Unique<VkImageView>		colorImageView		(makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
330 
331 	// Test attachment (depth or stencil)
332 	static const VkFormat stencilFormats[] =
333 	{
334 		// One of the following formats must be supported, as per spec requirement.
335 		VK_FORMAT_S8_UINT,
336 		VK_FORMAT_D16_UNORM_S8_UINT,
337 		VK_FORMAT_D24_UNORM_S8_UINT,
338 		VK_FORMAT_D32_SFLOAT_S8_UINT,
339 	};
340 
341 	const VkFormat testFormat = (m_testMode == MODE_STENCIL ? pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats)
342 															: VK_FORMAT_D16_UNORM);		// spec requires this format to be supported
343 	if (testFormat == VK_FORMAT_UNDEFINED)
344 		return tcu::TestStatus::fail("Required depth/stencil format not supported");
345 
346 	if (m_useTestAttachment)
347 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format " << getFormatName(testFormat) << tcu::TestLog::EndMessage;
348 
349 	const VkImageSubresourceRange	testSubresourceRange	= makeImageSubresourceRange(getImageAspectFlags(testFormat), 0u, 1u, 0u, 1u);
350 	const Unique<VkImage>			testImage				(makeImage(vk, device, makeImageCreateInfo(renderSize, testFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)));
351 	const UniquePtr<Allocation>		testImageAlloc			(bindImage(vk, device, allocator, *testImage, MemoryRequirement::Any));
352 	const Unique<VkImageView>		testImageView			(makeImageView(vk, device, *testImage, VK_IMAGE_VIEW_TYPE_2D, testFormat, testSubresourceRange));
353 	const VkImageView				attachmentImages[]		= { *colorImageView, *testImageView };
354 	const deUint32					numUsedAttachmentImages = (m_useTestAttachment ? 2u : 1u);
355 
356 	// Vertex buffer
357 
358 	const deUint32					numVertices				= 6;
359 	const VkDeviceSize				vertexBufferSizeBytes	= sizeof(tcu::Vec4) * numVertices;
360 	const Unique<VkBuffer>			vertexBuffer			(makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
361 	const UniquePtr<Allocation>		vertexBufferAlloc		(bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
362 
363 	{
364 		tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
365 
366 		pVertices[0] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
367 		pVertices[1] = tcu::Vec4(-1.0f, -1.0f,  0.0f,  1.0f);
368 		pVertices[2] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
369 
370 		pVertices[3] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
371 		pVertices[4] = tcu::Vec4( 1.0f,  1.0f,  1.0f,  1.0f);
372 		pVertices[5] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
373 
374 		flushAlloc(vk, device, *vertexBufferAlloc);
375 		// No barrier needed, flushed memory is automatically visible
376 	}
377 
378 	// Result buffer
379 
380 	const VkDeviceSize				resultBufferSizeBytes	= sizeof(deUint32);
381 	const Unique<VkBuffer>			resultBuffer			(makeBuffer(vk, device, resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
382 	const UniquePtr<Allocation>		resultBufferAlloc		(bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));
383 
384 	{
385 		deUint32* const pData = static_cast<deUint32*>(resultBufferAlloc->getHostPtr());
386 
387 		*pData = 0;
388 		flushAlloc(vk, device, *resultBufferAlloc);
389 	}
390 
391 	// Render result buffer (to retrieve color attachment contents)
392 
393 	const VkDeviceSize				colorBufferSizeBytes	= tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
394 	const Unique<VkBuffer>			colorBuffer				(makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
395 	const UniquePtr<Allocation>		colorBufferAlloc		(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
396 
397 	// Descriptors
398 
399 	const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
400 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
401 		.build(vk, device));
402 
403 	const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
404 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
405 		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
406 
407 	const Unique<VkDescriptorSet> descriptorSet				 (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
408 	const VkDescriptorBufferInfo  resultBufferDescriptorInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
409 
410 	DescriptorSetUpdateBuilder()
411 		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo)
412 		.update(vk, device);
413 
414 	// Pipeline
415 
416 	const Unique<VkShaderModule>	vertexModule  (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
417 	const Unique<VkShaderModule>	fragmentModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
418 	const Unique<VkRenderPass>		renderPass	  (makeRenderPass(vk, device, colorFormat, m_useTestAttachment, testFormat));
419 	const Unique<VkFramebuffer>		framebuffer	  (makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages, renderSize.x(), renderSize.y()));
420 	const Unique<VkPipelineLayout>	pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
421 	const Unique<VkPipeline>		pipeline	  (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, renderSize,
422 												  (m_testMode == MODE_DEPTH), (m_testMode == MODE_STENCIL)));
423 	const Unique<VkCommandPool>		cmdPool		  (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
424 	const Unique<VkCommandBuffer>	cmdBuffer	  (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
425 
426 	// Draw commands
427 
428 	{
429 		const VkRect2D renderArea = {
430 			makeOffset2D(0, 0),
431 			makeExtent2D(renderSize.x(), renderSize.y()),
432 		};
433 		const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
434 		const VkDeviceSize vertexBufferOffset = 0ull;
435 
436 		beginCommandBuffer(vk, *cmdBuffer);
437 
438 		{
439 			const VkImageMemoryBarrier barriers[] = {
440 				makeImageMemoryBarrier(
441 					0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
442 					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
443 					*colorImage, colorSubresourceRange),
444 				makeImageMemoryBarrier(
445 					0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
446 					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
447 					*testImage, testSubresourceRange),
448 			};
449 
450 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
451 				0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
452 		}
453 
454 		// Will clear the attachments with specified depth and stencil values.
455 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor, 0.5f, 0u);
456 
457 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
458 		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
459 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
460 
461 		// Mask half of the attachment image with value that will pass the stencil test.
462 		if (m_useTestAttachment && m_testMode == MODE_STENCIL)
463 			commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0), makeExtent2D(renderSize.x()/2, renderSize.y()), 1u);
464 
465 		vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
466 		endRenderPass(vk, *cmdBuffer);
467 
468 		copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, renderSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
469 
470 		endCommandBuffer(vk, *cmdBuffer);
471 		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
472 	}
473 
474 	// Log result image
475 	{
476 		invalidateAlloc(vk, device, *colorBufferAlloc);
477 
478 		const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc->getHostPtr());
479 
480 		tcu::TestLog& log = m_context.getTestContext().getLog();
481 		log << tcu::TestLog::Image("color0", "Rendered image", imagePixelAccess);
482 	}
483 
484 	// Verify results
485 	{
486 		invalidateAlloc(vk, device, *resultBufferAlloc);
487 
488 		const int  actualCounter	   = *static_cast<deInt32*>(resultBufferAlloc->getHostPtr());
489 		const bool expectPartialResult = (m_useEarlyTests && m_useTestAttachment);
490 		const int  expectedCounter	   = expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y();
491 		const int  tolerance		   = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3	: 0;
492 		const int  expectedMin         = de::max(0, expectedCounter - tolerance);
493 		const int  expectedMax		   = expectedCounter + tolerance;
494 
495 		tcu::TestLog& log = m_context.getTestContext().getLog();
496 		log << tcu::TestLog::Message << "Expected value"
497 			<< (expectPartialResult ? " in range: [" + de::toString(expectedMin) + ", " + de::toString(expectedMax) + "]" : ": " + de::toString(expectedCounter))
498 			<< tcu::TestLog::EndMessage;
499 		log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage;
500 
501 		if (expectedMin <= actualCounter && actualCounter <= expectedMax)
502 			return tcu::TestStatus::pass("Success");
503 		else
504 			return tcu::TestStatus::fail("Value out of range");
505 	}
506 }
507 
createInstance(Context & context) const508 TestInstance* EarlyFragmentTest::createInstance (Context& context) const
509 {
510 	return new EarlyFragmentTestInstance(context, m_flags);
511 }
512 
checkSupport(Context & context) const513 void EarlyFragmentTest::checkSupport (Context& context) const
514 {
515 	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
516 }
517 
518 class EarlyFragmentDiscardTestInstance : public EarlyFragmentTestInstance
519 {
520 public:
521 							EarlyFragmentDiscardTestInstance	(Context& context, const deUint32 flags);
522 
523 	tcu::TestStatus			iterate								(void);
524 
525 private:
526 	tcu::TextureLevel	generateReferenceColorImage				(const tcu::TextureFormat format, const tcu::IVec2& renderSize);
527 	enum TestMode
528 	{
529 		MODE_INVALID,
530 		MODE_DEPTH,
531 		MODE_STENCIL,
532 	};
533 
534 	const TestMode			m_testMode;
535 	const bool				m_useTestAttachment;
536 	const bool				m_useEarlyTests;
537 };
538 
EarlyFragmentDiscardTestInstance(Context & context,const deUint32 flags)539 EarlyFragmentDiscardTestInstance::EarlyFragmentDiscardTestInstance (Context& context, const deUint32 flags)
540 	: EarlyFragmentTestInstance			(context, flags)
541 	, m_testMode			(flags & FLAG_TEST_DEPTH   ? MODE_DEPTH :
542 							 flags & FLAG_TEST_STENCIL ? MODE_STENCIL : MODE_INVALID)
543 	, m_useTestAttachment	((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0)
544 	, m_useEarlyTests		((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0)
545 {
546 	DE_ASSERT(m_testMode != MODE_INVALID);
547 }
548 
generateReferenceColorImage(const tcu::TextureFormat format,const tcu::IVec2 & renderSize)549 tcu::TextureLevel EarlyFragmentDiscardTestInstance::generateReferenceColorImage(const tcu::TextureFormat format, const tcu::IVec2 &renderSize)
550 {
551 	tcu::TextureLevel	image(format, renderSize.x(), renderSize.y());
552 	const tcu::Vec4		clearColor	= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
553 
554 	tcu::clear(image.getAccess(), clearColor);
555 
556 	return image;
557 }
558 
iterate(void)559 tcu::TestStatus EarlyFragmentDiscardTestInstance::iterate (void)
560 {
561 	const DeviceInterface&		vk					= m_context.getDeviceInterface();
562 	const InstanceInterface&	vki					= m_context.getInstanceInterface();
563 	const VkDevice				device				= m_context.getDevice();
564 	const VkPhysicalDevice		physDevice			= m_context.getPhysicalDevice();
565 	const VkQueue				queue				= m_context.getUniversalQueue();
566 	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
567 	Allocator&					allocator			= m_context.getDefaultAllocator();
568 
569 	DE_ASSERT(m_useTestAttachment);
570 
571 	// Color attachment
572 	const tcu::IVec2				renderSize				= tcu::IVec2(32, 32);
573 	const VkFormat					colorFormat				= VK_FORMAT_R8G8B8A8_UNORM;
574 	const VkImageSubresourceRange	colorSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
575 	const Unique<VkImage>			colorImage				(makeImage(vk, device, makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
576 	const UniquePtr<Allocation>		colorImageAlloc			(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
577 	const Unique<VkImageView>		colorImageView			(makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
578 
579 	// Test attachment (depth or stencil)
580 	static const VkFormat stencilFormats[] =
581 	{
582 		// One of the following formats must be supported, as per spec requirement.
583 		VK_FORMAT_S8_UINT,
584 		VK_FORMAT_D16_UNORM_S8_UINT,
585 		VK_FORMAT_D24_UNORM_S8_UINT,
586 		VK_FORMAT_D32_SFLOAT_S8_UINT,
587 	};
588 
589 	const VkFormat depthStencilFormat = (m_testMode == MODE_STENCIL ? pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats)
590 										 : VK_FORMAT_D16_UNORM);		// spec requires this format to be supported
591 
592 	if (depthStencilFormat == VK_FORMAT_UNDEFINED)
593 		return tcu::TestStatus::fail("Required depth/stencil format not supported");
594 
595 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format " << getFormatName(depthStencilFormat) << tcu::TestLog::EndMessage;
596 
597 	const VkImageSubresourceRange	testSubresourceRange	= makeImageSubresourceRange(getImageAspectFlags(depthStencilFormat), 0u, 1u, 0u, 1u);
598 	const Unique<VkImage>			testImage				(makeImage(vk, device, makeImageCreateInfo(renderSize, depthStencilFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
599 	const UniquePtr<Allocation>		testImageAlloc			(bindImage(vk, device, allocator, *testImage, MemoryRequirement::Any));
600 	const Unique<VkImageView>		testImageView			(makeImageView(vk, device, *testImage, VK_IMAGE_VIEW_TYPE_2D, depthStencilFormat, testSubresourceRange));
601 	const VkImageView				attachmentImages[]		= { *colorImageView, *testImageView };
602 	const deUint32					numUsedAttachmentImages = DE_LENGTH_OF_ARRAY(attachmentImages);
603 
604 	// Vertex buffer
605 
606 	const deUint32					numVertices				= 6;
607 	const VkDeviceSize				vertexBufferSizeBytes	= sizeof(tcu::Vec4) * numVertices;
608 	const Unique<VkBuffer>			vertexBuffer			(makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
609 	const UniquePtr<Allocation>		vertexBufferAlloc		(bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
610 
611 	{
612 		tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
613 
614 		pVertices[0] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
615 		pVertices[1] = tcu::Vec4(-1.0f, -1.0f,  0.0f,  1.0f);
616 		pVertices[2] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
617 
618 		pVertices[3] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
619 		pVertices[4] = tcu::Vec4( 1.0f,  1.0f,  1.0f,  1.0f);
620 		pVertices[5] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
621 
622 		flushAlloc(vk, device, *vertexBufferAlloc);
623 		// No barrier needed, flushed memory is automatically visible
624 	}
625 
626 	// Result buffer
627 
628 	const VkDeviceSize				resultBufferSizeBytes	= sizeof(deUint32);
629 	const Unique<VkBuffer>			resultBuffer			(makeBuffer(vk, device, resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
630 	const UniquePtr<Allocation>		resultBufferAlloc		(bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));
631 
632 	{
633 		deUint32* const pData = static_cast<deUint32*>(resultBufferAlloc->getHostPtr());
634 
635 		*pData = 0;
636 		flushAlloc(vk, device, *resultBufferAlloc);
637 	}
638 
639 	// Render result buffer (to retrieve color attachment contents)
640 
641 	const VkDeviceSize				colorBufferSizeBytes	= tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
642 	const Unique<VkBuffer>			colorBuffer				(makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
643 	const UniquePtr<Allocation>		colorBufferAlloc		(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
644 
645 	// Depth stencil result buffer (to retrieve depth-stencil attachment contents)
646 
647 	const VkDeviceSize				dsBufferSizeBytes	= tcu::getPixelSize(mapVkFormat(depthStencilFormat)) * renderSize.x() * renderSize.y();
648 	const Unique<VkBuffer>			dsBuffer			(makeBuffer(vk, device, dsBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
649 	const UniquePtr<Allocation>		dsBufferAlloc		(bindBuffer(vk, device, allocator, *dsBuffer, MemoryRequirement::HostVisible));
650 
651 	// Descriptors
652 
653 	const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
654 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
655 		.build(vk, device));
656 
657 	const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
658 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
659 		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
660 
661 	const Unique<VkDescriptorSet> descriptorSet				 (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
662 	const VkDescriptorBufferInfo  resultBufferDescriptorInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
663 
664 	DescriptorSetUpdateBuilder()
665 		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo)
666 		.update(vk, device);
667 
668 	// Pipeline
669 
670 	const Unique<VkShaderModule>	vertexModule  (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
671 	const Unique<VkShaderModule>	fragmentModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
672 	const Unique<VkRenderPass>		renderPass	  (makeRenderPass(vk, device, colorFormat, m_useTestAttachment, depthStencilFormat));
673 	const Unique<VkFramebuffer>		framebuffer	  (makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages, renderSize.x(), renderSize.y()));
674 	const Unique<VkPipelineLayout>	pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
675 	const Unique<VkPipeline>		pipeline	  (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, renderSize,
676 																		(m_testMode == MODE_DEPTH), (m_testMode == MODE_STENCIL),
677 																		VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_INCREMENT_AND_CLAMP));
678 	const Unique<VkCommandPool>		cmdPool		  (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
679 	const Unique<VkCommandBuffer>	cmdBuffer	  (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
680 
681 	// Draw commands
682 	{
683 		const VkRect2D renderArea = {
684 			makeOffset2D(0, 0),
685 			makeExtent2D(renderSize.x(), renderSize.y()),
686 		};
687 		const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
688 		const VkDeviceSize vertexBufferOffset = 0ull;
689 
690 		beginCommandBuffer(vk, *cmdBuffer);
691 
692 		{
693 			const VkImageMemoryBarrier barriers[] = {
694 				makeImageMemoryBarrier(
695 					0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
696 					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
697 					*colorImage, colorSubresourceRange),
698 				makeImageMemoryBarrier(
699 					0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
700 					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
701 					*testImage, testSubresourceRange),
702 			};
703 
704 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
705 				0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
706 		}
707 
708 		// Will clear the attachments with specified depth and stencil values.
709 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor, 0.5f, 3u);
710 
711 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
712 		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
713 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
714 
715 		// Mask half of the attachment image with value that will pass the stencil test.
716 		if (m_testMode == MODE_STENCIL)
717 			commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0), makeExtent2D(renderSize.x()/2, renderSize.y()), 1u);
718 
719 		vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
720 		endRenderPass(vk, *cmdBuffer);
721 
722 		copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, renderSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
723 		VkImageAspectFlags	dsAspect = m_testMode == MODE_DEPTH ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT;
724 		VkImageLayout		dsImageLayout = m_testMode == MODE_DEPTH ? VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
725 		copyImageToBuffer(vk, *cmdBuffer, *testImage, *dsBuffer, renderSize, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, dsImageLayout, 1u, dsAspect, dsAspect);
726 
727 		endCommandBuffer(vk, *cmdBuffer);
728 		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
729 	}
730 
731 	// Verify color output
732 	{
733 		invalidateAlloc(vk, device, *colorBufferAlloc);
734 
735 		const tcu::ConstPixelBufferAccess	imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc->getHostPtr());
736 		const tcu::TextureLevel				referenceImage	= generateReferenceColorImage(mapVkFormat(colorFormat), renderSize);
737 		if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", referenceImage.getAccess(), imagePixelAccess, tcu::Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
738 			printf("Rendered color image is not correct");
739 	}
740 
741 	// Verify depth-stencil output
742 	{
743 		invalidateAlloc(vk, device, *dsBufferAlloc);
744 		// the buffer holds only one aspect of d/s format
745 		tcu::TextureFormat format = vk::mapVkFormat(m_testMode == MODE_STENCIL ? VK_FORMAT_S8_UINT : depthStencilFormat);
746 		DE_ASSERT(format.order == tcu::TextureFormat::D || format.order == tcu::TextureFormat::S);
747 
748 		const tcu::ConstPixelBufferAccess	dsPixelAccess (format, renderSize.x(), renderSize.y(), 1, dsBufferAlloc->getHostPtr());
749 
750 		for(int z = 0; z < dsPixelAccess.getDepth(); z++)
751 		for(int y = 0; y < dsPixelAccess.getHeight(); y++)
752 		for(int x = 0; x < dsPixelAccess.getWidth(); x++)
753 		{
754 			float	depthValue		= (m_testMode == MODE_DEPTH) ? dsPixelAccess.getPixDepth(x, y, z) : 0.0f;
755 			int		stencilValue	= (m_testMode == MODE_STENCIL) ? dsPixelAccess.getPixStencil(x, y, z) : 0;
756 
757 			// Depth test should write to the depth buffer even when there is a discard in the fragment shader,
758 			// when early fragment tests are enabled. We allow some tolerance to account for precision error
759 			// on depth writes.
760 			if (m_testMode == MODE_DEPTH)
761 			{
762 				float tolerance = 0.0001f;
763 				if (m_useEarlyTests && ((x + y) < 31) && depthValue >= 0.50 + tolerance)
764 				{
765 					std::ostringstream error;
766 					error << "Rendered depth value [ "<< x << ", " << y << ", " << z << "] is not correct: " << depthValue << " >= 0.5f";
767 					TCU_FAIL(error.str().c_str());
768 				}
769 				// When early fragment tests are disabled, the depth test happens after the fragment shader, but as we are discarding
770 				// all fragments, the stored value in the depth buffer should be the clear one (0.5f).
771 				if (!m_useEarlyTests && deAbs(depthValue - 0.5f) > tolerance)
772 				{
773 					std::ostringstream error;
774 					error << "Rendered depth value [ "<< x << ", " << y << ", " << z << "] is not correct: " << depthValue << " != 0.5f";
775 					TCU_FAIL(error.str().c_str());
776 				}
777 			}
778 
779 			if (m_testMode == MODE_STENCIL)
780 			{
781 				if (m_useEarlyTests && ((x < 16 && stencilValue != 2u) || (x >= 16 && stencilValue != 4u)))
782 				{
783 					std::ostringstream error;
784 					error << "Rendered stencil value [ "<< x << ", " << y << ", " << z << "] is not correct: " << stencilValue << " != ";
785 					error << (x < 16 ? 2u : 4u);
786 					TCU_FAIL(error.str().c_str());
787 				}
788 
789 				if (!m_useEarlyTests && ((x < 16 && stencilValue != 1u) || (x >= 16 && stencilValue != 3u)))
790 				{
791 					std::ostringstream error;
792 					error << "Rendered stencil value [ "<< x << ", " << y << ", " << z << "] is not correct: " << stencilValue << " != ";
793 					error << (x < 16 ? 1u : 3u);
794 					TCU_FAIL(error.str().c_str());
795 				}
796 			}
797 		}
798 	}
799 
800 	// Verify we process all the fragments
801 	{
802 		invalidateAlloc(vk, device, *resultBufferAlloc);
803 
804 		const int  actualCounter	   = *static_cast<deInt32*>(resultBufferAlloc->getHostPtr());
805 		const bool expectPartialResult = m_useEarlyTests;
806 		const int  expectedCounter	   = expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y();
807 		const int  tolerance		   = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3	: 0;
808 		const int  expectedMin         = de::max(0, expectedCounter - tolerance);
809 		const int  expectedMax		   = expectedCounter + tolerance;
810 
811 		tcu::TestLog& log = m_context.getTestContext().getLog();
812 		log << tcu::TestLog::Message << "Expected value"
813 			<< (expectPartialResult ? " in range: [" + de::toString(expectedMin) + ", " + de::toString(expectedMax) + "]" : ": " + de::toString(expectedCounter))
814 			<< tcu::TestLog::EndMessage;
815 		log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage;
816 
817 		if (expectedMin <= actualCounter && actualCounter <= expectedMax)
818 			return tcu::TestStatus::pass("Success");
819 		else
820 			return tcu::TestStatus::fail("Value out of range");
821 	}
822 }
823 
824 class EarlyFragmentDiscardTest : public EarlyFragmentTest
825 {
826 public:
827 						EarlyFragmentDiscardTest	(tcu::TestContext&		testCtx,
828 													 const std::string		name,
829 													 const deUint32			flags);
830 
831 	void				initPrograms				(SourceCollections&		programCollection) const;
832 	TestInstance*		createInstance				(Context&				context) const;
833 
834 private:
835 	const deUint32		m_flags;
836 };
837 
EarlyFragmentDiscardTest(tcu::TestContext & testCtx,const std::string name,const deUint32 flags)838 EarlyFragmentDiscardTest::EarlyFragmentDiscardTest (tcu::TestContext& testCtx, const std::string name, const deUint32 flags)
839 	: EarlyFragmentTest	(testCtx, name, flags)
840 	, m_flags (flags)
841 {
842 }
843 
createInstance(Context & context) const844 TestInstance* EarlyFragmentDiscardTest::createInstance (Context& context) const
845 {
846 	return new EarlyFragmentDiscardTestInstance(context, m_flags);
847 }
848 
initPrograms(SourceCollections & programCollection) const849 void EarlyFragmentDiscardTest::initPrograms(SourceCollections &programCollection) const
850 {
851 	// Vertex
852 	{
853 		std::ostringstream src;
854 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
855 			<< "\n"
856 			<< "layout(location = 0) in highp vec4 position;\n"
857 			<< "\n"
858 			<< "out gl_PerVertex {\n"
859 			<< "   vec4 gl_Position;\n"
860 			<< "};\n"
861 			<< "\n"
862 			<< "void main (void)\n"
863 			<< "{\n"
864 			<< "    gl_Position = position;\n"
865 			<< "}\n";
866 
867 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
868 	}
869 
870 	// Fragment
871 	{
872 		const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0;
873 		std::ostringstream src;
874 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
875 			<< "\n"
876 			<< (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "")
877 			<< "layout(location = 0) out highp vec4 fragColor;\n"
878 			<< "\n"
879 			<< "layout(binding = 0) coherent buffer Output {\n"
880 			<< "    uint result;\n"
881 			<< "} sb_out;\n"
882 			<< "\n"
883 			<< "void main (void)\n"
884 			<< "{\n"
885 			<< "    atomicAdd(sb_out.result, 1u);\n"
886 			<< "    gl_FragDepth = 0.75f;\n"
887 			<< "    fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
888 			<< "    discard;\n"
889 			<< "}\n";
890 
891 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
892 	}
893 }
894 
895 class EarlyFragmentSampleMaskTestInstance : public EarlyFragmentTestInstance
896 {
897 public:
898 							EarlyFragmentSampleMaskTestInstance	(Context& context, const deUint32 flags, const deUint32 sampleCount);
899 
900 	tcu::TestStatus			iterate								(void);
901 
902 private:
903 	tcu::TextureLevel	generateReferenceColorImage				(const tcu::TextureFormat format, const tcu::IVec2& renderSize);
904 	Move<VkRenderPass>  makeRenderPass							(const DeviceInterface&				vk,
905 																 const VkDevice						device,
906 																 const VkFormat						colorFormat,
907 																 const VkFormat						depthStencilFormat);
908 	Move<VkPipeline>	makeGraphicsPipeline					(const DeviceInterface&	vk,
909 																 const VkDevice			device,
910 																 const VkPipelineLayout	pipelineLayout,
911 																 const VkRenderPass		renderPass,
912 																 const VkShaderModule		vertexModule,
913 																 const VkShaderModule		fragmentModule,
914 																 const tcu::IVec2&		renderSize,
915 																 const bool				enableDepthTest,
916 																 const bool				enableStencilTest,
917 																 const VkStencilOp		stencilFailOp,
918 																 const VkStencilOp		stencilPassOp);
919 	enum TestMode
920 	{
921 		MODE_INVALID,
922 		MODE_DEPTH,
923 		MODE_STENCIL,
924 	};
925 
926 	const TestMode			m_testMode;
927 	const bool				m_useTestAttachment;
928 	const bool				m_useEarlyTests;
929 	const deUint32			m_sampleCount;
930 };
931 
EarlyFragmentSampleMaskTestInstance(Context & context,const deUint32 flags,const deUint32 sampleCount)932 EarlyFragmentSampleMaskTestInstance::EarlyFragmentSampleMaskTestInstance (Context& context, const deUint32 flags, const deUint32 sampleCount)
933 	: EarlyFragmentTestInstance			(context, flags)
934 	, m_testMode			(flags & FLAG_TEST_DEPTH   ? MODE_DEPTH :
935 							 flags & FLAG_TEST_STENCIL ? MODE_STENCIL : MODE_INVALID)
936 	, m_useTestAttachment	((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0)
937 	, m_useEarlyTests		((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0)
938 	, m_sampleCount			(sampleCount)
939 {
940 	DE_ASSERT(m_testMode != MODE_INVALID);
941 }
942 
generateReferenceColorImage(const tcu::TextureFormat format,const tcu::IVec2 & renderSize)943 tcu::TextureLevel EarlyFragmentSampleMaskTestInstance::generateReferenceColorImage(const tcu::TextureFormat format, const tcu::IVec2 &renderSize)
944 {
945 	tcu::TextureLevel	image(format, renderSize.x(), renderSize.y());
946 	const tcu::Vec4		clearColor	= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
947 
948 	tcu::clear(image.getAccess(), clearColor);
949 
950 	return image;
951 }
952 
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)953 Move<VkPipeline> EarlyFragmentSampleMaskTestInstance::makeGraphicsPipeline (const DeviceInterface&	vk,
954 																			const VkDevice			device,
955 																			const VkPipelineLayout	pipelineLayout,
956 																			const VkRenderPass		renderPass,
957 																			const VkShaderModule		vertexModule,
958 																			const VkShaderModule		fragmentModule,
959 																			const tcu::IVec2&		renderSize,
960 																			const bool				enableDepthTest,
961 																			const bool				enableStencilTest,
962 																			const VkStencilOp		stencilFailOp,
963 																			const VkStencilOp		stencilPassOp)
964 {
965 	const std::vector<VkViewport>			viewports					(1, makeViewport(renderSize));
966 	const std::vector<VkRect2D>				scissors					(1, makeRect2D(renderSize));
967 
968 	const VkStencilOpState					stencilOpState				= makeStencilOpState(
969 		stencilFailOp,			// stencil fail
970 		stencilPassOp,			// depth & stencil pass
971 		VK_STENCIL_OP_KEEP,		// depth only fail
972 		VK_COMPARE_OP_EQUAL,	// compare op
973 		0x3,					// compare mask
974 		0xf,					// write mask
975 		1u);					// reference
976 
977 	const VkPipelineDepthStencilStateCreateInfo	depthStencilStateCreateInfo	=
978 	{
979 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType                          sType
980 		DE_NULL,													// const void*                              pNext
981 		0u,															// VkPipelineDepthStencilStateCreateFlags   flags
982 		enableDepthTest ? VK_TRUE : VK_FALSE,						// VkBool32                                 depthTestEnable
983 		enableDepthTest ? VK_TRUE : VK_FALSE,						// VkBool32                                 depthWriteEnable
984 		VK_COMPARE_OP_LESS,											// VkCompareOp                              depthCompareOp
985 		VK_FALSE,													// VkBool32                                 depthBoundsTestEnable
986 		enableStencilTest ? VK_TRUE : VK_FALSE,						// VkBool32                                 stencilTestEnable
987 		stencilOpState,												// VkStencilOpState                         front
988 		stencilOpState,												// VkStencilOpState                         back
989 		0.0f,														// float                                    minDepthBounds
990 		1.0f														// float                                    maxDepthBounds
991 	};
992 
993 	// Only allow coverage on sample 0.
994 	const VkSampleMask sampleMask = 0x1;
995 
996 	const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo =
997 	{
998 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType
999 		DE_NULL,													// const void*								pNext
1000 		0u,															// VkPipelineMultisampleStateCreateFlags	flags
1001 		(VkSampleCountFlagBits)m_sampleCount,						// VkSampleCountFlagBits					rasterizationSamples
1002 		DE_TRUE,													// VkBool32									sampleShadingEnable
1003 		0.0f,														// float									minSampleShading
1004 		&sampleMask,												// const VkSampleMask*						pSampleMask
1005 		DE_FALSE,													// VkBool32									alphaToCoverageEnable
1006 		DE_FALSE,													// VkBool32									alphaToOneEnable
1007 	};
1008 
1009 	return vk::makeGraphicsPipeline(vk,										// const DeviceInterface&                        vk
1010 									device,									// const VkDevice                                device
1011 									pipelineLayout,							// const VkPipelineLayout                        pipelineLayout
1012 									vertexModule,							// const VkShaderModule                          vertexShaderModule
1013 									DE_NULL,								// const VkShaderModule                          tessellationControlModule
1014 									DE_NULL,								// const VkShaderModule                          tessellationEvalModule
1015 									DE_NULL,								// const VkShaderModule                          geometryShaderModule
1016 									fragmentModule,							// const VkShaderModule                          fragmentShaderModule
1017 									renderPass,								// const VkRenderPass                            renderPass
1018 									viewports,								// const std::vector<VkViewport>&                viewports
1019 									scissors,								// const std::vector<VkRect2D>&                  scissors
1020 									VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology                     topology
1021 									0u,										// const deUint32                                subpass
1022 									0u,										// const deUint32                                patchControlPoints
1023 									DE_NULL,								// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
1024 									DE_NULL,								// const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
1025 									&multisampleStateCreateInfo,			// const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
1026 									&depthStencilStateCreateInfo);			// const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
1027 }
1028 
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const VkFormat depthStencilFormat)1029 Move<VkRenderPass> EarlyFragmentSampleMaskTestInstance::makeRenderPass (const DeviceInterface&				vk,
1030 																		const VkDevice						device,
1031 																		const VkFormat						colorFormat,
1032 																		const VkFormat						depthStencilFormat)
1033 {
1034 	const bool								hasColor							= colorFormat != VK_FORMAT_UNDEFINED;
1035 	const bool								hasDepthStencil						= depthStencilFormat != VK_FORMAT_UNDEFINED;
1036 
1037 
1038 	const VkAttachmentDescription2			colorAttachmentDescription			=
1039 	{
1040 		VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,	// VkStructureType					sType;
1041 		DE_NULL,									// const void*						pNext;
1042 		(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags    flags
1043 		colorFormat,								// VkFormat                        format
1044 		(VkSampleCountFlagBits)m_sampleCount,		// VkSampleCountFlagBits           samples
1045 		VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp              loadOp
1046 		VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp             storeOp
1047 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp              stencilLoadOp
1048 		VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp             stencilStoreOp
1049 		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout                   initialLayout
1050 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout                   finalLayout
1051 	};
1052 
1053 	const VkAttachmentDescription2			depthStencilAttachmentDescription	=
1054 	{
1055 		VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,			// VkStructureType					sType;
1056 		DE_NULL,											// const void*						pNext;
1057 		(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags    flags
1058 		depthStencilFormat,									// VkFormat                        format
1059 		(VkSampleCountFlagBits)m_sampleCount,				// VkSampleCountFlagBits           samples
1060 		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp              loadOp
1061 		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp             storeOp
1062 		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp              stencilLoadOp
1063 		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp             stencilStoreOp
1064 		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout                   initialLayout
1065 		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL	// VkImageLayout                   finalLayout
1066 	};
1067 
1068 	const VkAttachmentDescription2			resolveAttachmentDescription			=
1069 	{
1070 		VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,	// VkStructureType					sType;
1071 		DE_NULL,									// const void*						pNext;
1072 		(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags    flags
1073 		colorFormat,								// VkFormat                        format
1074 		VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits           samples
1075 		VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp              loadOp
1076 		VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp             storeOp
1077 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp              stencilLoadOp
1078 		VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp             stencilStoreOp
1079 		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout                   initialLayout
1080 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout                   finalLayout
1081 	};
1082 
1083 		const VkAttachmentDescription2		resolveDepthStencilAttachmentDescription	=
1084 	{
1085 		VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,			// VkStructureType					sType;
1086 		DE_NULL,											// const void*						pNext;
1087 		(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags    flags
1088 		depthStencilFormat,									// VkFormat                        format
1089 		VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits           samples
1090 		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp              loadOp
1091 		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp             storeOp
1092 		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp              stencilLoadOp
1093 		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp             stencilStoreOp
1094 		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout                   initialLayout
1095 		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL	// VkImageLayout                   finalLayout
1096 	};
1097 
1098 	std::vector<VkAttachmentDescription2>	attachmentDescriptions;
1099 
1100 	if (hasColor)
1101 		attachmentDescriptions.push_back(colorAttachmentDescription);
1102 	if (hasDepthStencil)
1103 		attachmentDescriptions.push_back(depthStencilAttachmentDescription);
1104 	if (hasColor)
1105 		attachmentDescriptions.push_back(resolveAttachmentDescription);
1106 	if (hasDepthStencil)
1107 		attachmentDescriptions.push_back(resolveDepthStencilAttachmentDescription);
1108 
1109 	const VkAttachmentReference2				colorAttachmentRef					=
1110 	{
1111 		VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,			// VkStructureType		sType;
1112 		DE_NULL,											// const void*			pNext;
1113 		0u,													// deUint32         attachment
1114 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout    layout
1115 		VK_IMAGE_ASPECT_COLOR_BIT							// VkImageAspectFlags	aspectMask;
1116 	};
1117 
1118 	const VkAttachmentReference2				depthStencilAttachmentRef			=
1119 	{
1120 		VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,												// VkStructureType		sType;
1121 		DE_NULL,																				// const void*			pNext;
1122 	    hasDepthStencil ? 1u : 0u,																// deUint32         attachment
1123 		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,										// VkImageLayout    layout
1124 	    m_testMode == MODE_DEPTH ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT		// VkImageAspectFlags	aspectMask;
1125 	};
1126 
1127 	const VkAttachmentReference2				resolveAttachmentRef					=
1128 	{
1129 		VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,			// VkStructureType		sType;
1130 		DE_NULL,											// const void*			pNext;
1131 		hasColor ? 2u : 0u,									// deUint32         attachment
1132 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout    layout
1133 		VK_IMAGE_ASPECT_COLOR_BIT							// VkImageAspectFlags	aspectMask;
1134 	};
1135 
1136 	const VkAttachmentReference2				depthStencilResolveAttachmentRef			=
1137 	{
1138 		VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,												// VkStructureType		sType;
1139 		DE_NULL,																				// const void*			pNext;
1140 	    hasDepthStencil ? 3u : 0u,																// deUint32         attachment
1141 		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,										// VkImageLayout    layout
1142 	    m_testMode == MODE_DEPTH ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT		// VkImageAspectFlags	aspectMask;
1143 	};
1144 
1145 	// Using VK_RESOLVE_MODE_SAMPLE_ZERO_BIT as resolve mode, so no need to check its support as it is mandatory in the extension.
1146 	const VkSubpassDescriptionDepthStencilResolve depthStencilResolveDescription =
1147 	{
1148 		VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE,	// VkStructureType					sType;
1149 		DE_NULL,														// const void*						pNext;
1150 		VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,								// VkResolveModeFlagBits			depthResolveMode;
1151 		VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,								// VkResolveModeFlagBits			stencilResolveMode;
1152 		&depthStencilResolveAttachmentRef								// const VkAttachmentReference2*	pDepthStencilResolveAttachment;
1153 	};
1154 
1155 	const VkSubpassDescription2				subpassDescription					=
1156 	{
1157 		VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,						// VkStructureType					sType;
1158 		hasDepthStencil ? &depthStencilResolveDescription : DE_NULL,	// const void*						pNext;
1159 		(VkSubpassDescriptionFlags)0,									// VkSubpassDescriptionFlags		flags
1160 		VK_PIPELINE_BIND_POINT_GRAPHICS,								// VkPipelineBindPoint				pipelineBindPoint
1161 		0u,																// deUint32							viewMask;
1162 		0u,																// deUint32							inputAttachmentCount
1163 		DE_NULL,														// const VkAttachmentReference2*	pInputAttachments
1164 		hasColor ? 1u : 0u,												// deUint32							colorAttachmentCount
1165 		hasColor ? &colorAttachmentRef : DE_NULL,						// const VkAttachmentReference2*	pColorAttachments
1166 		hasColor ? &resolveAttachmentRef : DE_NULL,						// const VkAttachmentReference2*	pResolveAttachments
1167 		hasDepthStencil ? &depthStencilAttachmentRef : DE_NULL,			// const VkAttachmentReference2*	pDepthStencilAttachment
1168 		0u,																// deUint32							preserveAttachmentCount
1169 		DE_NULL															// const deUint32*					pPreserveAttachments
1170 	};
1171 
1172 	const VkRenderPassCreateInfo2			renderPassInfo						=
1173 	{
1174 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,								// VkStructureType                   sType
1175 		DE_NULL,																	// const void*                       pNext
1176 		(VkRenderPassCreateFlags)0,													// VkRenderPassCreateFlags           flags
1177 		(deUint32)attachmentDescriptions.size(),									// deUint32                          attachmentCount
1178 		attachmentDescriptions.size() > 0 ? &attachmentDescriptions[0] : DE_NULL,	// const VkAttachmentDescription2*    pAttachments
1179 		1u,																			// deUint32                          subpassCount
1180 		&subpassDescription,														// const VkSubpassDescription2*       pSubpasses
1181 		0u,																			// deUint32                          dependencyCount
1182 		DE_NULL,																	// const VkSubpassDependency*        pDependencies
1183 		0u,																			// deUint32						correlatedViewMaskCount;
1184 		DE_NULL,																	// const deUint32*					pCorrelatedViewMasks;
1185 	};
1186 
1187 	return createRenderPass2(vk, device, &renderPassInfo, DE_NULL);
1188 }
1189 
iterate(void)1190 tcu::TestStatus EarlyFragmentSampleMaskTestInstance::iterate (void)
1191 {
1192 	const DeviceInterface&		vk					= m_context.getDeviceInterface();
1193 	const InstanceInterface&	vki					= m_context.getInstanceInterface();
1194 	const VkDevice				device				= m_context.getDevice();
1195 	const VkPhysicalDevice		physDevice			= m_context.getPhysicalDevice();
1196 	const VkQueue				queue				= m_context.getUniversalQueue();
1197 	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1198 	Allocator&					allocator			= m_context.getDefaultAllocator();
1199 	const VkFormat				colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
1200 
1201 	DE_ASSERT(m_useTestAttachment);
1202 	DE_UNREF(m_useTestAttachment);
1203 
1204 	// Test attachment (depth or stencil)
1205 	static const VkFormat stencilFormats[] =
1206 	{
1207 		// One of the following formats must be supported, as per spec requirement.
1208 		VK_FORMAT_S8_UINT,
1209 		VK_FORMAT_D16_UNORM_S8_UINT,
1210 		VK_FORMAT_D24_UNORM_S8_UINT,
1211 		VK_FORMAT_D32_SFLOAT_S8_UINT,
1212 	};
1213 
1214 	const VkFormat depthStencilFormat = (m_testMode == MODE_STENCIL ? pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats)
1215 										 : VK_FORMAT_D16_UNORM);		// spec requires this format to be supported
1216 
1217 	if (depthStencilFormat == VK_FORMAT_UNDEFINED)
1218 		return tcu::TestStatus::fail("Required depth/stencil format not supported");
1219 
1220 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format " << getFormatName(depthStencilFormat) << tcu::TestLog::EndMessage;
1221 
1222 	// Check support for MSAA image formats used in the test.
1223 	VkImageFormatProperties formatProperties;
1224 	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);
1225 	if ((formatProperties.sampleCounts & m_sampleCount) == 0)
1226 		TCU_THROW(NotSupportedError, "Format does not support this number of samples for color format");
1227 
1228 	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);
1229 	if ((formatProperties.sampleCounts & m_sampleCount) == 0)
1230 		TCU_THROW(NotSupportedError, "Format does not support this number of samples for depth-stencil format");
1231 
1232 	// Color attachment
1233 	const tcu::IVec2				renderSize				= tcu::IVec2(32, 32);
1234 	const VkImageSubresourceRange	colorSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1235 
1236 	const VkImageCreateInfo imageParams =
1237 	{
1238 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
1239 		DE_NULL,																	// const void*				pNext;
1240 		(VkImageCreateFlags)0,														// VkImageCreateFlags		flags;
1241 		VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
1242 		colorFormat,																// VkFormat					format;
1243 		makeExtent3D(renderSize.x(), renderSize.y(), 1),							// VkExtent3D				extent;
1244 		1u,																			// deUint32					mipLevels;
1245 		1u,																			// deUint32					arrayLayers;
1246 		(VkSampleCountFlagBits)m_sampleCount,										// VkSampleCountFlagBits	samples;
1247 		VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
1248 		VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
1249 		VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
1250 		0u,																			// deUint32					queueFamilyIndexCount;
1251 		DE_NULL,																	// const deUint32*			pQueueFamilyIndices;
1252 		VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout			initialLayout;
1253 	};
1254 	const Unique<VkImage>			colorImage				(makeImage(vk, device, imageParams));
1255 	const UniquePtr<Allocation>		colorImageAlloc			(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1256 	const Unique<VkImageView>		colorImageView			(makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
1257 
1258 	const Unique<VkImage>			resolveColorImage		(makeImage(vk, device, makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
1259 	const UniquePtr<Allocation>		resolveColorImageAlloc	(bindImage(vk, device, allocator, *resolveColorImage, MemoryRequirement::Any));
1260 	const Unique<VkImageView>		resolveColorImageView	(makeImageView(vk, device, *resolveColorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
1261 
1262 	// Depth-Stencil attachment
1263 	const VkImageSubresourceRange	depthStencilSubresourceRange	= makeImageSubresourceRange(getImageAspectFlags(depthStencilFormat), 0u, 1u, 0u, 1u);
1264 
1265 	const VkImageCreateInfo depthStencilImageParams =
1266 	{
1267 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,												// VkStructureType			sType;
1268 		DE_NULL,																			// const void*				pNext;
1269 		(VkImageCreateFlags)0,																// VkImageCreateFlags		flags;
1270 		VK_IMAGE_TYPE_2D,																	// VkImageType				imageType;
1271 		depthStencilFormat,																			// VkFormat					format;
1272 		makeExtent3D(renderSize.x(), renderSize.y(), 1),									// VkExtent3D				extent;
1273 		1u,																					// deUint32					mipLevels;
1274 		1u,																					// deUint32					arrayLayers;
1275 		(VkSampleCountFlagBits)m_sampleCount,												// VkSampleCountFlagBits	samples;
1276 		VK_IMAGE_TILING_OPTIMAL,															// VkImageTiling			tiling;
1277 		VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
1278 		VK_SHARING_MODE_EXCLUSIVE,															// VkSharingMode			sharingMode;
1279 		0u,																					// deUint32					queueFamilyIndexCount;
1280 		DE_NULL,																			// const deUint32*			pQueueFamilyIndices;
1281 		VK_IMAGE_LAYOUT_UNDEFINED,															// VkImageLayout			initialLayout;
1282 	};
1283 	const Unique<VkImage>			depthStencilImage				(makeImage(vk, device, depthStencilImageParams));
1284 	const UniquePtr<Allocation>		depthStencilImageAlloc			(bindImage(vk, device, allocator, *depthStencilImage, MemoryRequirement::Any));
1285 	const Unique<VkImageView>		depthStencilImageView			(makeImageView(vk, device, *depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, depthStencilFormat, depthStencilSubresourceRange));
1286 
1287 	const Unique<VkImage>			resolveDepthStencilImage				(makeImage(vk, device, makeImageCreateInfo(renderSize, depthStencilFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
1288 	const UniquePtr<Allocation>		resolveDepthStencilImageAlloc			(bindImage(vk, device, allocator, *resolveDepthStencilImage, MemoryRequirement::Any));
1289 	const Unique<VkImageView>		resolveDepthStencilImageView			(makeImageView(vk, device, *resolveDepthStencilImage, VK_IMAGE_VIEW_TYPE_2D, depthStencilFormat, depthStencilSubresourceRange));
1290 
1291 	const VkImageView				attachmentImages[]		= { *colorImageView, *depthStencilImageView, *resolveColorImageView, *resolveDepthStencilImageView };
1292 	const deUint32					numUsedAttachmentImages = DE_LENGTH_OF_ARRAY(attachmentImages);
1293 
1294 	// Vertex buffer
1295 
1296 	const deUint32					numVertices				= 6u;
1297 	const VkDeviceSize				vertexBufferSizeBytes	= sizeof(tcu::Vec4) * numVertices;
1298 	const Unique<VkBuffer>			vertexBuffer			(makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
1299 	const UniquePtr<Allocation>		vertexBufferAlloc		(bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
1300 
1301 	{
1302 		tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
1303 
1304 		pVertices[0] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
1305 		pVertices[1] = tcu::Vec4(-1.0f, -1.0f,  0.0f,  1.0f);
1306 		pVertices[2] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
1307 
1308 		pVertices[3] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
1309 		pVertices[4] = tcu::Vec4( 1.0f,  1.0f,  1.0f,  1.0f);
1310 		pVertices[5] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
1311 
1312 		flushAlloc(vk, device, *vertexBufferAlloc);
1313 		// No barrier needed, flushed memory is automatically visible
1314 	}
1315 
1316 	// Result buffer
1317 
1318 	const VkDeviceSize				resultBufferSizeBytes	= sizeof(deUint32);
1319 	const Unique<VkBuffer>			resultBuffer			(makeBuffer(vk, device, resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
1320 	const UniquePtr<Allocation>		resultBufferAlloc		(bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));
1321 
1322 	{
1323 		deUint32* const pData = static_cast<deUint32*>(resultBufferAlloc->getHostPtr());
1324 
1325 		*pData = 0;
1326 		flushAlloc(vk, device, *resultBufferAlloc);
1327 	}
1328 
1329 	// Render result buffer (to retrieve color attachment contents)
1330 
1331 	const VkDeviceSize				colorBufferSizeBytes	= tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
1332 	const Unique<VkBuffer>			colorBuffer				(makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1333 	const UniquePtr<Allocation>		colorBufferAlloc		(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1334 
1335 	// Depth stencil result buffer (to retrieve depth-stencil attachment contents)
1336 
1337 	const VkDeviceSize				dsBufferSizeBytes	= tcu::getPixelSize(mapVkFormat(depthStencilFormat)) * renderSize.x() * renderSize.y();
1338 	const Unique<VkBuffer>			dsBuffer			(makeBuffer(vk, device, dsBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1339 	const UniquePtr<Allocation>		dsBufferAlloc		(bindBuffer(vk, device, allocator, *dsBuffer, MemoryRequirement::HostVisible));
1340 
1341 	// Descriptors
1342 
1343 	const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
1344 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
1345 		.build(vk, device));
1346 
1347 	const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
1348 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1349 		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1350 
1351 	const Unique<VkDescriptorSet> descriptorSet				 (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1352 	const VkDescriptorBufferInfo  resultBufferDescriptorInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
1353 
1354 	DescriptorSetUpdateBuilder()
1355 		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo)
1356 		.update(vk, device);
1357 
1358 	// Pipeline
1359 
1360 	const Unique<VkShaderModule>	vertexModule  (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1361 	const Unique<VkShaderModule>	fragmentModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
1362 
1363 	const Unique<VkRenderPass>		renderPass	  (makeRenderPass(vk, device, colorFormat, depthStencilFormat));
1364 	const Unique<VkFramebuffer>		framebuffer	  (makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages, renderSize.x(), renderSize.y()));
1365 	const Unique<VkPipelineLayout>	pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
1366 	const Unique<VkPipeline>		pipeline	  (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, renderSize,
1367 																		(m_testMode == MODE_DEPTH), (m_testMode == MODE_STENCIL),
1368 																		VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_INCREMENT_AND_CLAMP));
1369 	const Unique<VkCommandPool>		cmdPool		  (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1370 	const Unique<VkCommandBuffer>	cmdBuffer	  (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1371 
1372 	// Draw commands
1373 
1374 	{
1375 		const VkRect2D renderArea = {
1376 			makeOffset2D(0, 0),
1377 			makeExtent2D(renderSize.x(), renderSize.y()),
1378 		};
1379 		const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1380 		const VkDeviceSize vertexBufferOffset = 0ull;
1381 
1382 		beginCommandBuffer(vk, *cmdBuffer);
1383 
1384 		{
1385 			const VkImageMemoryBarrier barriers[] = {
1386 				makeImageMemoryBarrier(
1387 					0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1388 					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1389 					*colorImage, colorSubresourceRange),
1390 				makeImageMemoryBarrier(
1391 					0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
1392 					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1393 					*depthStencilImage, depthStencilSubresourceRange),
1394 				makeImageMemoryBarrier(
1395 					0u,  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1396 					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1397 					*resolveColorImage, colorSubresourceRange),
1398 				makeImageMemoryBarrier(
1399 					0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
1400 					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1401 					*resolveDepthStencilImage, depthStencilSubresourceRange),
1402 			};
1403 
1404 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
1405 				0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1406 		}
1407 
1408 		// Will clear the attachments with specified depth and stencil values.
1409 		{
1410 			const VkClearValue			clearValues[]		=
1411 				{
1412 					makeClearValueColor(clearColor),						// attachment 0
1413 					makeClearValueDepthStencil(0.5f, 3u),					// attachment 1
1414 					makeClearValueColor(clearColor),						// attachment 2
1415 					makeClearValueDepthStencil(0.5f, 3u),					// attachment 3
1416 				};
1417 
1418 			const VkRenderPassBeginInfo	renderPassBeginInfo	=
1419 				{
1420 					VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,	// VkStructureType         sType;
1421 					DE_NULL,									// const void*             pNext;
1422 					*renderPass,								// VkRenderPass            renderPass;
1423 					*framebuffer,								// VkFramebuffer           framebuffer;
1424 					renderArea,									// VkRect2D                renderArea;
1425 					DE_LENGTH_OF_ARRAY(clearValues),			// deUint32                clearValueCount;
1426 					clearValues,								// const VkClearValue*     pClearValues;
1427 				};
1428 
1429 			vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1430 		}
1431 
1432 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1433 		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1434 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1435 
1436 		// Mask half of the attachment image with value that will pass the stencil test.
1437 		if (m_testMode == MODE_STENCIL)
1438 			commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0), makeExtent2D(renderSize.x()/2, renderSize.y()), 1u);
1439 
1440 		vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
1441 		endRenderPass(vk, *cmdBuffer);
1442 
1443 		copyImageToBuffer(vk, *cmdBuffer, *resolveColorImage, *colorBuffer, renderSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
1444 		VkImageAspectFlags dsAspect = m_testMode == MODE_DEPTH ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT;
1445 		copyImageToBuffer(vk, *cmdBuffer, *resolveDepthStencilImage, *dsBuffer, renderSize, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 1u, dsAspect, dsAspect);
1446 
1447 		endCommandBuffer(vk, *cmdBuffer);
1448 		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1449 	}
1450 
1451 	// Verify color output
1452 	{
1453 		invalidateAlloc(vk, device, *colorBufferAlloc);
1454 
1455 		const tcu::ConstPixelBufferAccess	imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc->getHostPtr());
1456 		const tcu::TextureLevel				referenceImage	= generateReferenceColorImage(mapVkFormat(colorFormat), renderSize);
1457 		if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", referenceImage.getAccess(), imagePixelAccess, tcu::Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
1458 			printf("Rendered color image is not correct");
1459 	}
1460 
1461 	// Verify depth-stencil output
1462 	{
1463 		invalidateAlloc(vk, device, *dsBufferAlloc);
1464 		tcu::TextureFormat format = mapVkFormat(depthStencilFormat);
1465 		const tcu::ConstPixelBufferAccess	dsPixelAccess (format, renderSize.x(), renderSize.y(), 1, dsBufferAlloc->getHostPtr());
1466 
1467 		for(int z = 0; z < dsPixelAccess.getDepth(); z++)
1468 		for(int y = 0; y < dsPixelAccess.getHeight(); y++)
1469 		for(int x = 0; x < dsPixelAccess.getWidth(); x++)
1470 		{
1471 			float	depthValue		= (m_testMode == MODE_DEPTH) ? dsPixelAccess.getPixDepth(x, y, z) : 0.0f;
1472 			int		stencilValue	= (m_testMode == MODE_STENCIL) ? dsPixelAccess.getPixStencil(x, y, z) : 0;
1473 
1474 			// Depth test should write to the depth buffer even when there is a discard in the fragment shader,
1475 			// when early fragment tests are enabled.
1476 			if (m_testMode == MODE_DEPTH)
1477 			{
1478 				if (m_useEarlyTests && ((x + y) < 31) && depthValue >= 0.5f)
1479 				{
1480 					std::ostringstream error;
1481 					error << "Rendered depth value [ "<< x << ", " << y << ", " << z << "] is not correct: " << depthValue << " >= 0.5f";
1482 					TCU_FAIL(error.str().c_str());
1483 				}
1484 				// When early fragment tests are disabled, the depth test happens after the fragment shader, but as we are discarding
1485 				// all fragments, the stored value in the depth buffer should be the clear one (0.5f).
1486 				if (!m_useEarlyTests && deAbs(depthValue - 0.5f) > 0.01f)
1487 				{
1488 					std::ostringstream error;
1489 					error << "Rendered depth value [ "<< x << ", " << y << ", " << z << "] is not correct: " << depthValue << " != 0.5f";
1490 					TCU_FAIL(error.str().c_str());
1491 				}
1492 			}
1493 
1494 			if (m_testMode == MODE_STENCIL)
1495 			{
1496 				if (m_useEarlyTests && ((x < 16 && stencilValue != 2u) || (x >= 16 && stencilValue != 4u)))
1497 				{
1498 					std::ostringstream error;
1499 					error << "Rendered stencil value [ "<< x << ", " << y << ", " << z << "] is not correct: " << stencilValue << " != ";
1500 					error << (x < 16 ? 2u : 4u);
1501 					TCU_FAIL(error.str().c_str());
1502 				}
1503 
1504 				if (!m_useEarlyTests && ((x < 16 && stencilValue != 1u) || (x >= 16 && stencilValue != 3u)))
1505 				{
1506 					std::ostringstream error;
1507 					error << "Rendered stencil value [ "<< x << ", " << y << ", " << z << "] is not correct: " << stencilValue << " != ";
1508 					error << (x < 16 ? 1u : 3u);
1509 					TCU_FAIL(error.str().c_str());
1510 				}
1511 			}
1512 		}
1513 	}
1514 
1515 	// Verify we process all the fragments
1516 	{
1517 		invalidateAlloc(vk, device, *resultBufferAlloc);
1518 
1519 		const int  actualCounter	   = *static_cast<deInt32*>(resultBufferAlloc->getHostPtr());
1520 		const bool expectPartialResult = m_useEarlyTests;
1521 		const int  expectedCounter	   = expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y();
1522 		const int  tolerance		   = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3	: 0;
1523 		const int  expectedMin         = de::max(0, expectedCounter - tolerance);
1524 
1525 		tcu::TestLog& log = m_context.getTestContext().getLog();
1526 		log << tcu::TestLog::Message << "Minimum expected value: " + de::toString(expectedMin) << tcu::TestLog::EndMessage;
1527 		log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage;
1528 
1529 		if (expectedMin <= actualCounter)
1530 			return tcu::TestStatus::pass("Success");
1531 		else
1532 			return tcu::TestStatus::fail("Value out of range");
1533 	}
1534 }
1535 
1536 class EarlyFragmentSampleMaskTest : public EarlyFragmentTest
1537 {
1538 public:
1539 						EarlyFragmentSampleMaskTest	(tcu::TestContext&		testCtx,
1540 													 const std::string		name,
1541 													 const deUint32			flags,
1542 													 const deUint32			sampleCount);
1543 
1544 	void				initPrograms				(SourceCollections&		programCollection) const override;
1545 	TestInstance*		createInstance				(Context&				context) const override;
1546 	void				checkSupport				(Context&				context) const override;
1547 
1548 private:
1549 	const deUint32		m_flags;
1550 	const deUint32		m_sampleCount;
1551 };
1552 
EarlyFragmentSampleMaskTest(tcu::TestContext & testCtx,const std::string name,const deUint32 flags,const deUint32 sampleCount)1553 EarlyFragmentSampleMaskTest::EarlyFragmentSampleMaskTest (tcu::TestContext& testCtx, const std::string name, const deUint32 flags, const deUint32 sampleCount)
1554 	: EarlyFragmentTest	(testCtx, name, flags)
1555 	, m_flags (flags)
1556 	, m_sampleCount (sampleCount)
1557 {
1558 }
1559 
createInstance(Context & context) const1560 TestInstance* EarlyFragmentSampleMaskTest::createInstance (Context& context) const
1561 {
1562 	return new EarlyFragmentSampleMaskTestInstance(context, m_flags, m_sampleCount);
1563 }
1564 
initPrograms(SourceCollections & programCollection) const1565 void EarlyFragmentSampleMaskTest::initPrograms(SourceCollections &programCollection) const
1566 {
1567 	// Vertex
1568 	{
1569 		std::ostringstream src;
1570 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1571 			<< "\n"
1572 			<< "layout(location = 0) in highp vec4 position;\n"
1573 			<< "\n"
1574 			<< "out gl_PerVertex {\n"
1575 			<< "   vec4 gl_Position;\n"
1576 			<< "};\n"
1577 			<< "\n"
1578 			<< "void main (void)\n"
1579 			<< "{\n"
1580 			<< "    gl_Position = position;\n"
1581 			<< "}\n";
1582 
1583 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1584 	}
1585 
1586 	// Fragment
1587 	{
1588 		const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0;
1589 		std::ostringstream src;
1590 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1591 			<< "\n"
1592 			<< (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "")
1593 			<< "layout(location = 0) out highp vec4 fragColor;\n"
1594 			<< "\n"
1595 			<< "layout(binding = 0) coherent buffer Output {\n"
1596 			<< "    uint result;\n"
1597 			<< "} sb_out;\n"
1598 			<< "\n"
1599 			<< "void main (void)\n"
1600 			<< "{\n"
1601 			<< "    atomicAdd(sb_out.result, 1u);\n"
1602 			<< "    gl_SampleMask[0] = 0x0;\n"
1603 			<< "    fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
1604 			<< "    discard;\n"
1605 			<< "}\n";
1606 
1607 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1608 	}
1609 }
1610 
checkSupport(Context & context) const1611 void EarlyFragmentSampleMaskTest::checkSupport(Context& context) const
1612 {
1613 	EarlyFragmentTest::checkSupport(context);
1614 
1615 	context.requireDeviceFunctionality("VK_KHR_depth_stencil_resolve");
1616 }
1617 
1618 } // anonymous ns
1619 
createEarlyFragmentTests(tcu::TestContext & testCtx)1620 tcu::TestCaseGroup* createEarlyFragmentTests (tcu::TestContext& testCtx)
1621 {
1622 	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "early_fragment", "early fragment test cases"));
1623 
1624 	{
1625 		static const struct
1626 		{
1627 			std::string caseName;
1628 			deUint32	flags;
1629 		} cases[] =
1630 		{
1631 			{ "no_early_fragment_tests_depth",					FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS									},
1632 			{ "no_early_fragment_tests_stencil",				FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS									},
1633 			{ "early_fragment_tests_depth",						FLAG_TEST_DEPTH																			},
1634 			{ "early_fragment_tests_stencil",					FLAG_TEST_STENCIL																		},
1635 			{ "no_early_fragment_tests_depth_no_attachment",	FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT	},
1636 			{ "no_early_fragment_tests_stencil_no_attachment",	FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT	},
1637 			{ "early_fragment_tests_depth_no_attachment",		FLAG_TEST_DEPTH   |										 FLAG_DONT_USE_TEST_ATTACHMENT	},
1638 			{ "early_fragment_tests_stencil_no_attachment",		FLAG_TEST_STENCIL |										 FLAG_DONT_USE_TEST_ATTACHMENT	},
1639 		};
1640 
1641 		for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
1642 			testGroup->addChild(new EarlyFragmentTest(testCtx, cases[i].caseName, cases[i].flags));
1643 	}
1644 
1645 	// Check that discard does not affect depth test writes.
1646 	{
1647 		static const struct
1648 		{
1649 			std::string caseName;
1650 			deUint32	flags;
1651 		} cases[] =
1652 		{
1653 			{ "discard_no_early_fragment_tests_depth",					FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS									},
1654 			{ "discard_no_early_fragment_tests_stencil",				FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS									},
1655 			{ "discard_early_fragment_tests_depth",						FLAG_TEST_DEPTH																			},
1656 			{ "discard_early_fragment_tests_stencil",					FLAG_TEST_STENCIL																		},
1657 		};
1658 
1659 		for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
1660 			testGroup->addChild(new EarlyFragmentDiscardTest(testCtx, cases[i].caseName, cases[i].flags));
1661 	}
1662 
1663 	// Check that writing to gl_SampleMask does not affect depth test writes.
1664 	{
1665 		static const struct
1666 		{
1667 			std::string caseName;
1668 			deUint32	flags;
1669 		} cases[] =
1670 		{
1671 			{ "samplemask_no_early_fragment_tests_depth",				FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS,									},
1672 			{ "samplemask_early_fragment_tests_depth",					FLAG_TEST_DEPTH,																		},
1673 		};
1674 
1675 		const VkSampleCountFlags sampleCounts[] = { VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT, VK_SAMPLE_COUNT_16_BIT };
1676 		const std::string sampleCountsStr[] = { "samples_2", "samples_4", "samples_8", "samples_16" };
1677 
1678 		for (deUint32 sampleCountsNdx = 0; sampleCountsNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountsNdx++)
1679 		{
1680 			for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
1681 				testGroup->addChild(new EarlyFragmentSampleMaskTest(testCtx, cases[i].caseName + "_" + sampleCountsStr[sampleCountsNdx], cases[i].flags, sampleCounts[sampleCountsNdx]));
1682         }
1683 	}
1684 
1685 	return testGroup.release();
1686 }
1687 
1688 } // FragmentOperations
1689 } // vkt
1690