• 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 
41 #include "deUniquePtr.hpp"
42 #include "deStringUtil.hpp"
43 
44 #include <string>
45 
46 namespace vkt
47 {
48 namespace FragmentOperations
49 {
50 namespace
51 {
52 using namespace vk;
53 using de::UniquePtr;
54 
55 //! Basic 2D image.
makeImageCreateInfo(const tcu::IVec2 & size,const VkFormat format,const VkImageUsageFlags usage)56 inline VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage)
57 {
58 	const VkImageCreateInfo imageParams =
59 	{
60 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,					// VkStructureType			sType;
61 		DE_NULL,												// const void*				pNext;
62 		(VkImageCreateFlags)0,									// VkImageCreateFlags		flags;
63 		VK_IMAGE_TYPE_2D,										// VkImageType				imageType;
64 		format,													// VkFormat					format;
65 		makeExtent3D(size.x(), size.y(), 1),					// VkExtent3D				extent;
66 		1u,														// deUint32					mipLevels;
67 		1u,														// deUint32					arrayLayers;
68 		VK_SAMPLE_COUNT_1_BIT,									// VkSampleCountFlagBits	samples;
69 		VK_IMAGE_TILING_OPTIMAL,								// VkImageTiling			tiling;
70 		usage,													// VkImageUsageFlags		usage;
71 		VK_SHARING_MODE_EXCLUSIVE,								// VkSharingMode			sharingMode;
72 		0u,														// deUint32					queueFamilyIndexCount;
73 		DE_NULL,												// const deUint32*			pQueueFamilyIndices;
74 		VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout			initialLayout;
75 	};
76 	return imageParams;
77 }
78 
beginRenderPass(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const VkRenderPass renderPass,const VkFramebuffer framebuffer,const VkRect2D & renderArea,const tcu::Vec4 & clearColor,const float clearDepth,const deUint32 clearStencil)79 void beginRenderPass (const DeviceInterface&	vk,
80 					  const VkCommandBuffer		commandBuffer,
81 					  const VkRenderPass		renderPass,
82 					  const VkFramebuffer		framebuffer,
83 					  const VkRect2D&			renderArea,
84 					  const tcu::Vec4&			clearColor,
85 					  const float				clearDepth,
86 					  const deUint32			clearStencil)
87 {
88 	const VkClearValue clearValues[] =
89 	{
90 		makeClearValueColor(clearColor),						// attachment 0
91 		makeClearValueDepthStencil(clearDepth, clearStencil),	// attachment 1
92 	};
93 
94 	const VkRenderPassBeginInfo renderPassBeginInfo = {
95 		VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,		// VkStructureType         sType;
96 		DE_NULL,										// const void*             pNext;
97 		renderPass,										// VkRenderPass            renderPass;
98 		framebuffer,									// VkFramebuffer           framebuffer;
99 		renderArea,										// VkRect2D                renderArea;
100 		DE_LENGTH_OF_ARRAY(clearValues),				// uint32_t                clearValueCount;
101 		clearValues,									// const VkClearValue*     pClearValues;
102 	};
103 
104 	vk.cmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
105 }
106 
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const bool useDepthStencilAttachment,const VkFormat depthStencilFormat)107 Move<VkRenderPass> makeRenderPass (const DeviceInterface&	vk,
108 								   const VkDevice			device,
109 								   const VkFormat			colorFormat,
110 								   const bool				useDepthStencilAttachment,
111 								   const VkFormat			depthStencilFormat)
112 {
113 	const VkAttachmentDescription attachments[] =
114 	{
115 		// color
116 		{
117 			(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
118 			colorFormat,										// VkFormat							format;
119 			VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
120 			VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
121 			VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
122 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
123 			VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
124 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
125 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					finalLayout;
126 		},
127 		// depth/stencil
128 		{
129 			(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
130 			depthStencilFormat,									// VkFormat							format;
131 			VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
132 			VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
133 			VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
134 			VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				stencilLoadOp;
135 			VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				stencilStoreOp;
136 			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout					initialLayout;
137 			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout					finalLayout;
138 		}
139 	};
140 
141 	const VkAttachmentReference unusedAttachmentReference =
142 	{
143 		VK_ATTACHMENT_UNUSED,								// deUint32			attachment;
144 		VK_IMAGE_LAYOUT_UNDEFINED							// VkImageLayout	layout;
145 	};
146 
147 	const VkAttachmentReference colorAttachmentReference =
148 	{
149 		0u,													// deUint32			attachment;
150 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
151 	};
152 
153 	const VkAttachmentReference depthStencilAttachmentReference =
154 	{
155 		1u,													// deUint32			attachment;
156 		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL	// VkImageLayout	layout;
157 	};
158 
159 	const VkAttachmentReference* pDepthStencilAttachment = (useDepthStencilAttachment ? &depthStencilAttachmentReference : &unusedAttachmentReference);
160 
161 	const VkSubpassDescription subpassDescription =
162 	{
163 		0u,													// VkSubpassDescriptionFlags		flags;
164 		VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
165 		0u,													// deUint32							inputAttachmentCount;
166 		DE_NULL,											// const VkAttachmentReference*		pInputAttachments;
167 		1u,													// deUint32							colorAttachmentCount;
168 		&colorAttachmentReference,							// const VkAttachmentReference*		pColorAttachments;
169 		DE_NULL,											// const VkAttachmentReference*		pResolveAttachments;
170 		pDepthStencilAttachment,							// const VkAttachmentReference*		pDepthStencilAttachment;
171 		0u,													// deUint32							preserveAttachmentCount;
172 		DE_NULL												// const deUint32*					pPreserveAttachments;
173 	};
174 
175 	const VkRenderPassCreateInfo renderPassInfo =
176 	{
177 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
178 		DE_NULL,											// const void*						pNext;
179 		(VkRenderPassCreateFlags)0,							// VkRenderPassCreateFlags			flags;
180 		(useDepthStencilAttachment ? 2u : 1u),				// deUint32							attachmentCount;
181 		attachments,										// const VkAttachmentDescription*	pAttachments;
182 		1u,													// deUint32							subpassCount;
183 		&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
184 		0u,													// deUint32							dependencyCount;
185 		DE_NULL												// const VkSubpassDependency*		pDependencies;
186 	};
187 
188 	return createRenderPass(vk, device, &renderPassInfo);
189 }
190 
makeFramebuffer(const DeviceInterface & vk,const VkDevice device,const VkRenderPass renderPass,const deUint32 attachmentCount,const VkImageView * pAttachments,const tcu::IVec2 size)191 Move<VkFramebuffer> makeFramebuffer (const DeviceInterface&		vk,
192 									 const VkDevice				device,
193 									 const VkRenderPass			renderPass,
194 									 const deUint32				attachmentCount,
195 									 const VkImageView*			pAttachments,
196 									 const tcu::IVec2			size)
197 {
198 	const VkFramebufferCreateInfo framebufferInfo = {
199 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,		// VkStructureType                             sType;
200 		DE_NULL,										// const void*                                 pNext;
201 		(VkFramebufferCreateFlags)0,					// VkFramebufferCreateFlags                    flags;
202 		renderPass,										// VkRenderPass                                renderPass;
203 		attachmentCount,								// uint32_t                                    attachmentCount;
204 		pAttachments,									// const VkImageView*                          pAttachments;
205 		static_cast<deUint32>(size.x()),				// uint32_t                                    width;
206 		static_cast<deUint32>(size.y()),				// uint32_t                                    height;
207 		1u,												// uint32_t                                    layers;
208 	};
209 
210 	return createFramebuffer(vk, device, &framebufferInfo);
211 }
212 
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)213 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&	vk,
214 									   const VkDevice			device,
215 									   const VkPipelineLayout	pipelineLayout,
216 									   const VkRenderPass		renderPass,
217 									   const VkShaderModule		vertexModule,
218 									   const VkShaderModule		fragmentModule,
219 									   const tcu::IVec2&		renderSize,
220 									   const bool				enableDepthTest,
221 									   const bool				enableStencilTest)
222 {
223 	const VkVertexInputBindingDescription vertexInputBindingDescription =
224 	{
225 		0u,								// uint32_t				binding;
226 		sizeof(tcu::Vec4),				// uint32_t				stride;		// Vertex is a 4-element vector XYZW, position only
227 		VK_VERTEX_INPUT_RATE_VERTEX,	// VkVertexInputRate	inputRate;
228 	};
229 
230 	const VkVertexInputAttributeDescription vertexInputAttributeDescription =
231 	{
232 		0u,									// uint32_t			location;
233 		0u,									// uint32_t			binding;
234 		VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat			format;
235 		0u,									// uint32_t			offset;
236 	};
237 
238 	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
239 	{
240 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType                             sType;
241 		DE_NULL,													// const void*                                 pNext;
242 		(VkPipelineVertexInputStateCreateFlags)0,					// VkPipelineVertexInputStateCreateFlags       flags;
243 		1u,															// uint32_t                                    vertexBindingDescriptionCount;
244 		&vertexInputBindingDescription,								// const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
245 		1u,															// uint32_t                                    vertexAttributeDescriptionCount;
246 		&vertexInputAttributeDescription,							// const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
247 	};
248 
249 	const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
250 	{
251 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType                             sType;
252 		DE_NULL,														// const void*                                 pNext;
253 		(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags     flags;
254 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							// VkPrimitiveTopology                         topology;
255 		VK_FALSE,														// VkBool32                                    primitiveRestartEnable;
256 	};
257 
258 	const VkViewport viewport = makeViewport(
259 		0.0f, 0.0f,
260 		static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()),
261 		0.0f, 1.0f);
262 
263 	const VkRect2D scissor = {
264 		makeOffset2D(0, 0),
265 		makeExtent2D(renderSize.x(), renderSize.y()),
266 	};
267 
268 	const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
269 	{
270 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,	// VkStructureType                             sType;
271 		DE_NULL,												// const void*                                 pNext;
272 		(VkPipelineViewportStateCreateFlags)0,					// VkPipelineViewportStateCreateFlags          flags;
273 		1u,														// uint32_t                                    viewportCount;
274 		&viewport,												// const VkViewport*                           pViewports;
275 		1u,														// uint32_t                                    scissorCount;
276 		&scissor,												// const VkRect2D*                             pScissors;
277 	};
278 
279 	const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
280 	{
281 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType                          sType;
282 		DE_NULL,														// const void*                              pNext;
283 		(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags  flags;
284 		VK_FALSE,														// VkBool32                                 depthClampEnable;
285 		VK_FALSE,														// VkBool32                                 rasterizerDiscardEnable;
286 		VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
287 		VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
288 		VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
289 		VK_FALSE,														// VkBool32									depthBiasEnable;
290 		0.0f,															// float									depthBiasConstantFactor;
291 		0.0f,															// float									depthBiasClamp;
292 		0.0f,															// float									depthBiasSlopeFactor;
293 		1.0f,															// float									lineWidth;
294 	};
295 
296 	const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
297 	{
298 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
299 		DE_NULL,													// const void*								pNext;
300 		(VkPipelineMultisampleStateCreateFlags)0,					// VkPipelineMultisampleStateCreateFlags	flags;
301 		VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples;
302 		VK_FALSE,													// VkBool32									sampleShadingEnable;
303 		0.0f,														// float									minSampleShading;
304 		DE_NULL,													// const VkSampleMask*						pSampleMask;
305 		VK_FALSE,													// VkBool32									alphaToCoverageEnable;
306 		VK_FALSE													// VkBool32									alphaToOneEnable;
307 	};
308 
309 	const VkStencilOpState stencilOpState = makeStencilOpState(
310 		VK_STENCIL_OP_KEEP,		// stencil fail
311 		VK_STENCIL_OP_KEEP,		// depth & stencil pass
312 		VK_STENCIL_OP_KEEP,		// depth only fail
313 		VK_COMPARE_OP_EQUAL,	// compare op
314 		1u,						// compare mask
315 		1u,						// write mask
316 		1u);					// reference
317 
318 	VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
319 	{
320 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
321 		DE_NULL,													// const void*								pNext;
322 		(VkPipelineDepthStencilStateCreateFlags)0,					// VkPipelineDepthStencilStateCreateFlags	flags;
323 		enableDepthTest,											// VkBool32									depthTestEnable;
324 		VK_TRUE,													// VkBool32									depthWriteEnable;
325 		VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
326 		VK_FALSE,													// VkBool32									depthBoundsTestEnable;
327 		enableStencilTest,											// VkBool32									stencilTestEnable;
328 		stencilOpState,												// VkStencilOpState							front;
329 		stencilOpState,												// VkStencilOpState							back;
330 		0.0f,														// float									minDepthBounds;
331 		1.0f,														// float									maxDepthBounds;
332 	};
333 
334 	const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
335 	// Number of blend attachments must equal the number of color attachments.
336 	const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
337 	{
338 		VK_FALSE,							// VkBool32					blendEnable;
339 		VK_BLEND_FACTOR_ONE,				// VkBlendFactor			srcColorBlendFactor;
340 		VK_BLEND_FACTOR_ZERO,				// VkBlendFactor			dstColorBlendFactor;
341 		VK_BLEND_OP_ADD,					// VkBlendOp				colorBlendOp;
342 		VK_BLEND_FACTOR_ONE,				// VkBlendFactor			srcAlphaBlendFactor;
343 		VK_BLEND_FACTOR_ZERO,				// VkBlendFactor			dstAlphaBlendFactor;
344 		VK_BLEND_OP_ADD,					// VkBlendOp				alphaBlendOp;
345 		colorComponentsAll,					// VkColorComponentFlags	colorWriteMask;
346 	};
347 
348 	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
349 	{
350 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
351 		DE_NULL,													// const void*									pNext;
352 		(VkPipelineColorBlendStateCreateFlags)0,					// VkPipelineColorBlendStateCreateFlags			flags;
353 		VK_FALSE,													// VkBool32										logicOpEnable;
354 		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
355 		1u,															// deUint32										attachmentCount;
356 		&pipelineColorBlendAttachmentState,							// const VkPipelineColorBlendAttachmentState*	pAttachments;
357 		{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConstants[4];
358 	};
359 
360 	const VkPipelineShaderStageCreateInfo pShaderStages[] =
361 	{
362 		{
363 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
364 			DE_NULL,												// const void*							pNext;
365 			(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags		flags;
366 			VK_SHADER_STAGE_VERTEX_BIT,								// VkShaderStageFlagBits				stage;
367 			vertexModule,											// VkShaderModule						module;
368 			"main",													// const char*							pName;
369 			DE_NULL,												// const VkSpecializationInfo*			pSpecializationInfo;
370 		},
371 		{
372 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
373 			DE_NULL,												// const void*							pNext;
374 			(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags		flags;
375 			VK_SHADER_STAGE_FRAGMENT_BIT,							// VkShaderStageFlagBits				stage;
376 			fragmentModule,											// VkShaderModule						module;
377 			"main",													// const char*							pName;
378 			DE_NULL,												// const VkSpecializationInfo*			pSpecializationInfo;
379 		}
380 	};
381 
382 	const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
383 	{
384 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
385 		DE_NULL,											// const void*										pNext;
386 		(VkPipelineCreateFlags)0,							// VkPipelineCreateFlags							flags;
387 		DE_LENGTH_OF_ARRAY(pShaderStages),					// deUint32											stageCount;
388 		pShaderStages,										// const VkPipelineShaderStageCreateInfo*			pStages;
389 		&vertexInputStateInfo,								// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
390 		&pipelineInputAssemblyStateInfo,					// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
391 		DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
392 		&pipelineViewportStateInfo,							// const VkPipelineViewportStateCreateInfo*			pViewportState;
393 		&pipelineRasterizationStateInfo,					// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
394 		&pipelineMultisampleStateInfo,						// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
395 		&pipelineDepthStencilStateInfo,						// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
396 		&pipelineColorBlendStateInfo,						// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
397 		DE_NULL,											// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
398 		pipelineLayout,										// VkPipelineLayout									layout;
399 		renderPass,											// VkRenderPass										renderPass;
400 		0u,													// deUint32											subpass;
401 		DE_NULL,											// VkPipeline										basePipelineHandle;
402 		0,													// deInt32											basePipelineIndex;
403 	};
404 
405 	return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
406 }
407 
makeBufferImageCopy(const VkImageAspectFlags aspectFlags,const tcu::IVec2 & renderSize)408 VkBufferImageCopy makeBufferImageCopy (const VkImageAspectFlags aspectFlags, const tcu::IVec2& renderSize)
409 {
410 	const VkBufferImageCopy copyParams =
411 	{
412 		0ull,															//	VkDeviceSize				bufferOffset;
413 		0u,																//	deUint32					bufferRowLength;
414 		0u,																//	deUint32					bufferImageHeight;
415 		makeImageSubresourceLayers(aspectFlags, 0u, 0u, 1u),			//	VkImageSubresourceLayers	imageSubresource;
416 		makeOffset3D(0, 0, 0),											//	VkOffset3D					imageOffset;
417 		makeExtent3D(renderSize.x(), renderSize.y(), 1u),				//	VkExtent3D					imageExtent;
418 	};
419 	return copyParams;
420 }
421 
commandClearStencilAttachment(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const VkOffset2D & offset,const VkExtent2D & extent,const deUint32 clearValue)422 void commandClearStencilAttachment (const DeviceInterface&	vk,
423 									const VkCommandBuffer	commandBuffer,
424 									const VkOffset2D&		offset,
425 									const VkExtent2D&		extent,
426 									const deUint32			clearValue)
427 {
428 	const VkClearAttachment stencilAttachment =
429 	{
430 		VK_IMAGE_ASPECT_STENCIL_BIT,					// VkImageAspectFlags    aspectMask;
431 		0u,												// uint32_t              colorAttachment;
432 		makeClearValueDepthStencil(0.0f, clearValue),	// VkClearValue          clearValue;
433 	};
434 
435 	const VkClearRect rect =
436 	{
437 		{ offset, extent },		// VkRect2D    rect;
438 		0u,						// uint32_t    baseArrayLayer;
439 		1u,						// uint32_t    layerCount;
440 	};
441 
442 	vk.cmdClearAttachments(commandBuffer, 1u, &stencilAttachment, 1u, &rect);
443 }
444 
getImageAspectFlags(const VkFormat format)445 VkImageAspectFlags getImageAspectFlags (const VkFormat format)
446 {
447 	const tcu::TextureFormat tcuFormat = mapVkFormat(format);
448 
449 	if      (tcuFormat.order == tcu::TextureFormat::DS)		return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
450 	else if (tcuFormat.order == tcu::TextureFormat::D)		return VK_IMAGE_ASPECT_DEPTH_BIT;
451 	else if (tcuFormat.order == tcu::TextureFormat::S)		return VK_IMAGE_ASPECT_STENCIL_BIT;
452 
453 	DE_ASSERT(false);
454 	return 0u;
455 }
456 
isSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,const VkPhysicalDevice device,const VkFormat format)457 bool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, const VkPhysicalDevice device, const VkFormat format)
458 {
459 	VkFormatProperties formatProps;
460 	instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
461 	return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
462 }
463 
pickSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,const VkPhysicalDevice device,const deUint32 numFormats,const VkFormat * pFormats)464 VkFormat pickSupportedDepthStencilFormat (const InstanceInterface&	instanceInterface,
465 										  const VkPhysicalDevice	device,
466 										  const deUint32			numFormats,
467 										  const VkFormat*			pFormats)
468 {
469 	for (deUint32 i = 0; i < numFormats; ++i)
470 		if (isSupportedDepthStencilFormat(instanceInterface, device, pFormats[i]))
471 			return pFormats[i];
472 	return VK_FORMAT_UNDEFINED;
473 }
474 
475 enum Flags
476 {
477 	FLAG_TEST_DEPTH							= 1u << 0,
478 	FLAG_TEST_STENCIL						= 1u << 1,
479 	FLAG_DONT_USE_TEST_ATTACHMENT			= 1u << 2,
480 	FLAG_DONT_USE_EARLY_FRAGMENT_TESTS		= 1u << 3,
481 };
482 
483 class EarlyFragmentTest : public TestCase
484 {
485 public:
486 						EarlyFragmentTest	(tcu::TestContext&		testCtx,
487 											 const std::string		name,
488 											 const deUint32			flags);
489 
490 	void				initPrograms		(SourceCollections&		programCollection) const;
491 	TestInstance*		createInstance		(Context&				context) const;
492 
493 private:
494 	const deUint32		m_flags;
495 };
496 
EarlyFragmentTest(tcu::TestContext & testCtx,const std::string name,const deUint32 flags)497 EarlyFragmentTest::EarlyFragmentTest (tcu::TestContext& testCtx, const std::string name, const deUint32 flags)
498 	: TestCase	(testCtx, name, "")
499 	, m_flags	(flags)
500 {
501 }
502 
initPrograms(SourceCollections & programCollection) const503 void EarlyFragmentTest::initPrograms (SourceCollections& programCollection) const
504 {
505 	// Vertex
506 	{
507 		std::ostringstream src;
508 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
509 			<< "\n"
510 			<< "layout(location = 0) in highp vec4 position;\n"
511 			<< "\n"
512 			<< "out gl_PerVertex {\n"
513 			<< "   vec4 gl_Position;\n"
514 			<< "};\n"
515 			<< "\n"
516 			<< "void main (void)\n"
517 			<< "{\n"
518 			<< "    gl_Position = position;\n"
519 			<< "}\n";
520 
521 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
522 	}
523 
524 	// Fragment
525 	{
526 		const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0;
527 		std::ostringstream src;
528 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
529 			<< "\n"
530 			<< (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "")
531 			<< "layout(location = 0) out highp vec4 fragColor;\n"
532 			<< "\n"
533 			<< "layout(binding = 0) coherent buffer Output {\n"
534 			<< "    uint result;\n"
535 			<< "} sb_out;\n"
536 			<< "\n"
537 			<< "void main (void)\n"
538 			<< "{\n"
539 			<< "    atomicAdd(sb_out.result, 1u);\n"
540 			<< "	fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
541 			<< "}\n";
542 
543 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
544 	}
545 }
546 
547 class EarlyFragmentTestInstance : public TestInstance
548 {
549 public:
550 							EarlyFragmentTestInstance (Context& context, const deUint32 flags);
551 
552 	tcu::TestStatus			iterate					  (void);
553 
554 private:
555 	enum TestMode
556 	{
557 		MODE_INVALID,
558 		MODE_DEPTH,
559 		MODE_STENCIL,
560 	};
561 
562 	const TestMode			m_testMode;
563 	const bool				m_useTestAttachment;
564 	const bool				m_useEarlyTests;
565 };
566 
EarlyFragmentTestInstance(Context & context,const deUint32 flags)567 EarlyFragmentTestInstance::EarlyFragmentTestInstance (Context& context, const deUint32 flags)
568 	: TestInstance			(context)
569 	, m_testMode			(flags & FLAG_TEST_DEPTH   ? MODE_DEPTH :
570 							 flags & FLAG_TEST_STENCIL ? MODE_STENCIL : MODE_INVALID)
571 	, m_useTestAttachment	((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0)
572 	, m_useEarlyTests		((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0)
573 {
574 	DE_ASSERT(m_testMode != MODE_INVALID);
575 }
576 
iterate(void)577 tcu::TestStatus EarlyFragmentTestInstance::iterate (void)
578 {
579 	const DeviceInterface&		vk					= m_context.getDeviceInterface();
580 	const InstanceInterface&	vki					= m_context.getInstanceInterface();
581 	const VkDevice				device				= m_context.getDevice();
582 	const VkPhysicalDevice		physDevice			= m_context.getPhysicalDevice();
583 	const VkQueue				queue				= m_context.getUniversalQueue();
584 	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
585 	Allocator&					allocator			= m_context.getDefaultAllocator();
586 
587 	// Color attachment
588 
589 	const tcu::IVec2				renderSize			= tcu::IVec2(32, 32);
590 	const VkFormat					colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
591 	const VkImageSubresourceRange	colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
592 	const Unique<VkImage>			colorImage			(makeImage(vk, device, makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
593 	const UniquePtr<Allocation>		colorImageAlloc		(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
594 	const Unique<VkImageView>		colorImageView		(makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
595 
596 	// Test attachment (depth or stencil)
597 	static const VkFormat stencilFormats[] =
598 	{
599 		// One of the following formats must be supported, as per spec requirement.
600 		VK_FORMAT_S8_UINT,
601 		VK_FORMAT_D16_UNORM_S8_UINT,
602 		VK_FORMAT_D24_UNORM_S8_UINT,
603 		VK_FORMAT_D32_SFLOAT_S8_UINT,
604 	};
605 
606 	const VkFormat testFormat = (m_testMode == MODE_STENCIL ? pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats)
607 															: VK_FORMAT_D16_UNORM);		// spec requires this format to be supported
608 	if (testFormat == VK_FORMAT_UNDEFINED)
609 		return tcu::TestStatus::fail("Required depth/stencil format not supported");
610 
611 	if (m_useTestAttachment)
612 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format " << getFormatName(testFormat) << tcu::TestLog::EndMessage;
613 
614 	const VkImageSubresourceRange	testSubresourceRange	= makeImageSubresourceRange(getImageAspectFlags(testFormat), 0u, 1u, 0u, 1u);
615 	const Unique<VkImage>			testImage				(makeImage(vk, device, makeImageCreateInfo(renderSize, testFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)));
616 	const UniquePtr<Allocation>		testImageAlloc			(bindImage(vk, device, allocator, *testImage, MemoryRequirement::Any));
617 	const Unique<VkImageView>		testImageView			(makeImageView(vk, device, *testImage, VK_IMAGE_VIEW_TYPE_2D, testFormat, testSubresourceRange));
618 	const VkImageView				attachmentImages[]		= { *colorImageView, *testImageView };
619 	const deUint32					numUsedAttachmentImages = (m_useTestAttachment ? 2u : 1u);
620 
621 	// Vertex buffer
622 
623 	const deUint32					numVertices				= 6;
624 	const VkDeviceSize				vertexBufferSizeBytes	= sizeof(tcu::Vec4) * numVertices;
625 	const Unique<VkBuffer>			vertexBuffer			(makeBuffer(vk, device, makeBufferCreateInfo(vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)));
626 	const UniquePtr<Allocation>		vertexBufferAlloc		(bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
627 
628 	{
629 		tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
630 
631 		pVertices[0] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
632 		pVertices[1] = tcu::Vec4(-1.0f, -1.0f,  0.0f,  1.0f);
633 		pVertices[2] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
634 
635 		pVertices[3] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
636 		pVertices[4] = tcu::Vec4( 1.0f,  1.0f,  1.0f,  1.0f);
637 		pVertices[5] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
638 
639 		flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSizeBytes);
640 		// No barrier needed, flushed memory is automatically visible
641 	}
642 
643 	// Result buffer
644 
645 	const VkDeviceSize				resultBufferSizeBytes	= sizeof(deUint32);
646 	const Unique<VkBuffer>			resultBuffer			(makeBuffer(vk, device, makeBufferCreateInfo(resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)));
647 	const UniquePtr<Allocation>		resultBufferAlloc		(bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));
648 
649 	{
650 		deUint32* const pData = static_cast<deUint32*>(resultBufferAlloc->getHostPtr());
651 
652 		*pData = 0;
653 		flushMappedMemoryRange(vk, device, resultBufferAlloc->getMemory(), resultBufferAlloc->getOffset(), resultBufferSizeBytes);
654 	}
655 
656 	// Render result buffer (to retrieve color attachment contents)
657 
658 	const VkDeviceSize				colorBufferSizeBytes	= tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
659 	const Unique<VkBuffer>			colorBuffer				(makeBuffer(vk, device, makeBufferCreateInfo(colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
660 	const UniquePtr<Allocation>		colorBufferAlloc		(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
661 
662 	// Descriptors
663 
664 	const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
665 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
666 		.build(vk, device));
667 
668 	const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
669 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
670 		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
671 
672 	const Unique<VkDescriptorSet> descriptorSet				 (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
673 	const VkDescriptorBufferInfo  resultBufferDescriptorInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
674 
675 	DescriptorSetUpdateBuilder()
676 		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo)
677 		.update(vk, device);
678 
679 	// Pipeline
680 
681 	const Unique<VkShaderModule>	vertexModule  (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
682 	const Unique<VkShaderModule>	fragmentModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
683 	const Unique<VkRenderPass>		renderPass	  (makeRenderPass(vk, device, colorFormat, m_useTestAttachment, testFormat));
684 	const Unique<VkFramebuffer>		framebuffer	  (makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages, renderSize));
685 	const Unique<VkPipelineLayout>	pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
686 	const Unique<VkPipeline>		pipeline	  (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, renderSize,
687 												  (m_testMode == MODE_DEPTH), (m_testMode == MODE_STENCIL)));
688 	const Unique<VkCommandPool>		cmdPool		  (makeCommandPool(vk, device, queueFamilyIndex));
689 	const Unique<VkCommandBuffer>	cmdBuffer	  (makeCommandBuffer(vk, device, *cmdPool));
690 
691 	// Draw commands
692 
693 	{
694 		const VkRect2D renderArea = {
695 			makeOffset2D(0, 0),
696 			makeExtent2D(renderSize.x(), renderSize.y()),
697 		};
698 		const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
699 		const VkDeviceSize vertexBufferOffset = 0ull;
700 
701 		beginCommandBuffer(vk, *cmdBuffer);
702 
703 		{
704 			const VkImageMemoryBarrier barriers[] = {
705 				makeImageMemoryBarrier(
706 					0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
707 					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
708 					*colorImage, colorSubresourceRange),
709 				makeImageMemoryBarrier(
710 					0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
711 					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
712 					*testImage, testSubresourceRange),
713 			};
714 
715 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
716 				0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
717 		}
718 
719 		// Will clear the attachments with specified depth and stencil values.
720 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor, 0.5f, 0u);
721 
722 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
723 		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
724 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
725 
726 		// Mask half of the attachment image with value that will pass the stencil test.
727 		if (m_useTestAttachment && m_testMode == MODE_STENCIL)
728 			commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0), makeExtent2D(renderSize.x()/2, renderSize.y()), 1u);
729 
730 		vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
731 		vk.cmdEndRenderPass(*cmdBuffer);
732 
733 		{
734 			const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(
735 				VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *resultBuffer, 0ull, resultBufferSizeBytes);
736 
737 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
738 				0u, DE_NULL, 1u, &shaderWriteBarrier, 0u, DE_NULL);
739 
740 			const VkImageMemoryBarrier preCopyColorImageBarrier = makeImageMemoryBarrier(
741 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
742 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
743 				*colorImage, colorSubresourceRange);
744 
745 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
746 				0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyColorImageBarrier);
747 
748 			const VkBufferImageCopy copyRegion = makeBufferImageCopy(VK_IMAGE_ASPECT_COLOR_BIT, renderSize);
749 			vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &copyRegion);
750 
751 			const VkBufferMemoryBarrier postCopyColorBufferBarrier = makeBufferMemoryBarrier(
752 				VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, colorBufferSizeBytes);
753 
754 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
755 				0u, DE_NULL, 1u, &postCopyColorBufferBarrier, 0u, DE_NULL);
756 		}
757 
758 		VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
759 		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
760 	}
761 
762 	// Log result image
763 	{
764 		invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), colorBufferSizeBytes);
765 
766 		const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc->getHostPtr());
767 
768 		tcu::TestLog& log = m_context.getTestContext().getLog();
769 		log << tcu::TestLog::Image("color0", "Rendered image", imagePixelAccess);
770 	}
771 
772 	// Verify results
773 	{
774 		invalidateMappedMemoryRange(vk, device, resultBufferAlloc->getMemory(), resultBufferAlloc->getOffset(), resultBufferSizeBytes);
775 
776 		const int  actualCounter	   = *static_cast<deInt32*>(resultBufferAlloc->getHostPtr());
777 		const bool expectPartialResult = (m_useEarlyTests && m_useTestAttachment);
778 		const int  expectedCounter	   = expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y();
779 		const int  tolerance		   = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3	: 0;
780 		const int  expectedMin         = de::max(0, expectedCounter - tolerance);
781 		const int  expectedMax		   = expectedCounter + tolerance;
782 
783 		tcu::TestLog& log = m_context.getTestContext().getLog();
784 		log << tcu::TestLog::Message << "Expected value"
785 			<< (expectPartialResult ? " in range: [" + de::toString(expectedMin) + ", " + de::toString(expectedMax) + "]" : ": " + de::toString(expectedCounter))
786 			<< tcu::TestLog::EndMessage;
787 		log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage;
788 
789 		if (expectedMin <= actualCounter && actualCounter <= expectedMax)
790 			return tcu::TestStatus::pass("Success");
791 		else
792 			return tcu::TestStatus::fail("Value out of range");
793 	}
794 }
795 
createInstance(Context & context) const796 TestInstance* EarlyFragmentTest::createInstance (Context& context) const
797 {
798 	// Check required features
799 	{
800 		VkPhysicalDeviceFeatures features;
801 		context.getInstanceInterface().getPhysicalDeviceFeatures(context.getPhysicalDevice(), &features);
802 
803 		// SSBO writes in fragment shader
804 		if (!features.fragmentStoresAndAtomics)
805 			throw tcu::NotSupportedError("Missing required feature: fragmentStoresAndAtomics");
806 	}
807 
808 	return new EarlyFragmentTestInstance(context, m_flags);
809 }
810 
811 } // anonymous ns
812 
createEarlyFragmentTests(tcu::TestContext & testCtx)813 tcu::TestCaseGroup* createEarlyFragmentTests (tcu::TestContext& testCtx)
814 {
815 	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "early_fragment", "early fragment test cases"));
816 
817 	static const struct
818 	{
819 		std::string caseName;
820 		deUint32	flags;
821 	} cases[] =
822 	{
823 		{ "no_early_fragment_tests_depth",					FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS									},
824 		{ "no_early_fragment_tests_stencil",				FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS									},
825 		{ "early_fragment_tests_depth",						FLAG_TEST_DEPTH																			},
826 		{ "early_fragment_tests_stencil",					FLAG_TEST_STENCIL																		},
827 		{ "no_early_fragment_tests_depth_no_attachment",	FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT	},
828 		{ "no_early_fragment_tests_stencil_no_attachment",	FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT	},
829 		{ "early_fragment_tests_depth_no_attachment",		FLAG_TEST_DEPTH   |										 FLAG_DONT_USE_TEST_ATTACHMENT  },
830 		{ "early_fragment_tests_stencil_no_attachment",		FLAG_TEST_STENCIL |										 FLAG_DONT_USE_TEST_ATTACHMENT	},
831 	};
832 
833 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
834 		testGroup->addChild(new EarlyFragmentTest(testCtx, cases[i].caseName, cases[i].flags));
835 
836 	return testGroup.release();
837 }
838 
839 } // FragmentOperations
840 } // vkt
841