• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7  * Copyright (c) 2016 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Shader builtin variable tests.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktShaderRenderBuiltinVarTests.hpp"
27 
28 #include "tcuFloat.hpp"
29 #include "deUniquePtr.hpp"
30 #include "vkDefs.hpp"
31 #include "vktShaderRender.hpp"
32 #include "gluShaderUtil.hpp"
33 #include "tcuImageCompare.hpp"
34 #include "tcuStringTemplate.hpp"
35 #include "tcuTextureUtil.hpp"
36 #include "tcuTestLog.hpp"
37 #include "vktDrawUtil.hpp"
38 #include "vkImageUtil.hpp"
39 #include "vkTypeUtil.hpp"
40 #include "vkMemUtil.hpp"
41 #include "vkCmdUtil.hpp"
42 
43 #include "deMath.h"
44 #include "deRandom.hpp"
45 
46 #include <map>
47 
48 using namespace std;
49 using namespace tcu;
50 using namespace vk;
51 using namespace de;
52 
53 namespace vkt
54 {
55 using namespace drawutil;
56 
57 namespace sr
58 {
59 
60 namespace
61 {
62 
63 enum
64 {
65 	FRONTFACE_RENDERWIDTH			= 16,
66 	FRONTFACE_RENDERHEIGHT			= 16
67 };
68 
69 class FrontFacingVertexShader : public rr::VertexShader
70 {
71 public:
FrontFacingVertexShader(void)72 	FrontFacingVertexShader (void)
73 		: rr::VertexShader(1, 0)
74 	{
75 		m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
76 	}
77 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const78 	void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
79 	{
80 		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
81 		{
82 			packets[packetNdx]->position = rr::readVertexAttribFloat(inputs[0],
83 																	 packets[packetNdx]->instanceNdx,
84 																	 packets[packetNdx]->vertexNdx);
85 		}
86 	}
87 };
88 
89 class FrontFacingFragmentShader : public rr::FragmentShader
90 {
91 public:
FrontFacingFragmentShader(void)92 	FrontFacingFragmentShader (void)
93 		: rr::FragmentShader(0, 1)
94 	{
95 		m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
96 	}
97 
shadeFragments(rr::FragmentPacket *,const int numPackets,const rr::FragmentShadingContext & context) const98 	void shadeFragments (rr::FragmentPacket* , const int numPackets, const rr::FragmentShadingContext& context) const
99 	{
100 		tcu::Vec4 color;
101 		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
102 		{
103 			for (int fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; ++fragNdx)
104 			{
105 				if (context.visibleFace == rr::FACETYPE_FRONT)
106 					color = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
107 				else
108 					color = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
109 				rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
110 			}
111 		}
112 	}
113 };
114 
115 class BuiltinGlFrontFacingCaseInstance : public ShaderRenderCaseInstance
116 {
117 public:
118 					BuiltinGlFrontFacingCaseInstance	(Context& context, VkPrimitiveTopology topology);
119 
120 	TestStatus		iterate								(void);
121 private:
122 	const VkPrimitiveTopology							m_topology;
123 };
124 
BuiltinGlFrontFacingCaseInstance(Context & context,VkPrimitiveTopology topology)125 BuiltinGlFrontFacingCaseInstance::BuiltinGlFrontFacingCaseInstance (Context& context, VkPrimitiveTopology topology)
126 	: ShaderRenderCaseInstance	(context)
127 	, m_topology				(topology)
128 {
129 }
130 
131 
iterate(void)132 TestStatus BuiltinGlFrontFacingCaseInstance::iterate (void)
133 {
134 	TestLog&					log				= m_context.getTestContext().getLog();
135 	std::vector<Vec4>			vertices;
136 	std::vector<VulkanShader>	shaders;
137 	FrontFacingVertexShader		vertexShader;
138 	FrontFacingFragmentShader	fragmentShader;
139 	std::string					testDesc;
140 
141 	vertices.push_back(Vec4( -0.75f,	-0.75f,	0.0f,	1.0f));
142 	vertices.push_back(Vec4(  0.0f,		-0.75f,	0.0f,	1.0f));
143 	vertices.push_back(Vec4( -0.37f,	0.75f,	0.0f,	1.0f));
144 	vertices.push_back(Vec4(  0.37f,	0.75f,	0.0f,	1.0f));
145 	vertices.push_back(Vec4(  0.75f,	-0.75f,	0.0f,	1.0f));
146 	vertices.push_back(Vec4(  0.0f,		-0.75f,	0.0f,	1.0f));
147 
148 	shaders.push_back(VulkanShader(VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("vert")));
149 	shaders.push_back(VulkanShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("frag")));
150 
151 	testDesc = "gl_FrontFacing " + getPrimitiveTopologyShortName(m_topology) + " ";
152 
153 	DrawState					drawState		(m_topology, FRONTFACE_RENDERWIDTH, FRONTFACE_RENDERHEIGHT);
154 	DrawCallData				drawCallData	(vertices);
155 	VulkanProgram				vulkanProgram	(shaders);
156 
157 	VulkanDrawContext			dc(m_context, drawState, drawCallData, vulkanProgram);
158 	dc.draw();
159 
160 	ReferenceDrawContext		refDrawContext(drawState, drawCallData, vertexShader, fragmentShader);
161 	refDrawContext.draw();
162 
163 	log << TestLog::Image( "reference",
164 							"reference",
165 							tcu::ConstPixelBufferAccess(tcu::TextureFormat(
166 									refDrawContext.getColorPixels().getFormat()),
167 									refDrawContext.getColorPixels().getWidth(),
168 									refDrawContext.getColorPixels().getHeight(),
169 									1,
170 									refDrawContext.getColorPixels().getDataPtr()));
171 
172 	log << TestLog::Image(	"result",
173 							"result",
174 							tcu::ConstPixelBufferAccess(tcu::TextureFormat(
175 									dc.getColorPixels().getFormat()),
176 									dc.getColorPixels().getWidth(),
177 									dc.getColorPixels().getHeight(),
178 									1,
179 									dc.getColorPixels().getDataPtr()));
180 
181 	if (tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
182 												  "ComparisonResult",
183 												  "Image comparison result",
184 												  refDrawContext.getColorPixels(),
185 												  dc.getColorPixels(),
186 												  UVec4(0u),
187 												  IVec3(1,1,0),
188 												  false,
189 												  tcu::COMPARE_LOG_RESULT))
190 	{
191 		testDesc += "passed";
192 		return tcu::TestStatus::pass(testDesc.c_str());
193 	}
194 	else
195 	{
196 		testDesc += "failed";
197 		return tcu::TestStatus::fail(testDesc.c_str());
198 	}
199 }
200 
201 class BuiltinGlFrontFacingCase : public TestCase
202 {
203 public:
204 								BuiltinGlFrontFacingCase	(TestContext& testCtx, VkPrimitiveTopology topology, const char* name, const char* description);
205 	virtual						~BuiltinGlFrontFacingCase	(void);
206 
207 	void						initPrograms				(SourceCollections& dst) const;
208 	TestInstance*				createInstance				(Context& context) const;
209 
210 private:
211 								BuiltinGlFrontFacingCase	(const BuiltinGlFrontFacingCase&);	// not allowed!
212 	BuiltinGlFrontFacingCase&	operator=					(const BuiltinGlFrontFacingCase&);	// not allowed!
213 
214 	const VkPrimitiveTopology	m_topology;
215 };
216 
BuiltinGlFrontFacingCase(TestContext & testCtx,VkPrimitiveTopology topology,const char * name,const char * description)217 BuiltinGlFrontFacingCase::BuiltinGlFrontFacingCase (TestContext& testCtx, VkPrimitiveTopology topology, const char* name, const char* description)
218 	: TestCase					(testCtx, name, description)
219 	, m_topology				(topology)
220 {
221 }
222 
~BuiltinGlFrontFacingCase(void)223 BuiltinGlFrontFacingCase::~BuiltinGlFrontFacingCase (void)
224 {
225 }
226 
initPrograms(SourceCollections & programCollection) const227 void BuiltinGlFrontFacingCase::initPrograms (SourceCollections& programCollection) const
228 {
229 	{
230 		std::ostringstream vertexSource;
231 		vertexSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
232 			<< "\n"
233 			<< "layout(location = 0) in highp vec4 position;\n"
234 			<< "void main()\n"
235 			<< "{\n"
236 			<< "gl_Position = position;\n"
237 			<< "gl_PointSize = 1.0;\n"
238 			<< "}\n";
239 		programCollection.glslSources.add("vert") << glu::VertexSource(vertexSource.str());
240 	}
241 
242 	{
243 		std::ostringstream fragmentSource;
244 		fragmentSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
245 			<< "\n"
246 			<< "layout(location = 0) out mediump vec4 color;\n"
247 			<< "void main()\n"
248 			<< "{\n"
249 			<< "if (gl_FrontFacing)\n"
250 			<< "	color = vec4(1.0, 0.0, 0.0, 1.0);\n"
251 			<< "else\n"
252 			<< "	color = vec4(0.0, 1.0, 0.0, 1.0);\n"
253 			<< "}\n";
254 		programCollection.glslSources.add("frag") << glu::FragmentSource(fragmentSource.str());
255 	}
256 }
257 
createInstance(Context & context) const258 TestInstance* BuiltinGlFrontFacingCase::createInstance (Context& context) const
259 {
260 	return new BuiltinGlFrontFacingCaseInstance(context, m_topology);
261 }
262 
263 class BuiltinFragDepthCaseInstance : public TestInstance
264 {
265 public:
266 	enum
267 	{
268 		RENDERWIDTH		= 16,
269 		RENDERHEIGHT	= 16
270 	};
271 					BuiltinFragDepthCaseInstance		(Context& context, VkPrimitiveTopology topology, VkFormat format, bool largeDepthEnable, float defaultDepth, bool depthClampEnable, const VkSampleCountFlagBits samples);
272 	TestStatus		iterate								(void);
273 
274 	bool			validateDepthBuffer					(const tcu::ConstPixelBufferAccess& validationBuffer, const tcu::ConstPixelBufferAccess& markerBuffer, const float tolerance) const;
275 private:
276 	const VkPrimitiveTopology		m_topology;
277 	const VkFormat					m_format;
278 	const bool						m_largeDepthEnable;
279 	const float						m_defaultDepthValue;
280 	const bool						m_depthClampEnable;
281 	const VkSampleCountFlagBits		m_samples;
282 	const tcu::UVec2				m_renderSize;
283 	const float						m_largeDepthBase;
284 };
285 
BuiltinFragDepthCaseInstance(Context & context,VkPrimitiveTopology topology,VkFormat format,bool largeDepthEnable,float defaultDepth,bool depthClampEnable,const VkSampleCountFlagBits samples)286 BuiltinFragDepthCaseInstance::BuiltinFragDepthCaseInstance (Context& context, VkPrimitiveTopology topology, VkFormat format, bool largeDepthEnable, float defaultDepth, bool depthClampEnable, const VkSampleCountFlagBits samples)
287 	: TestInstance			(context)
288 	, m_topology			(topology)
289 	, m_format				(format)
290 	, m_largeDepthEnable	(largeDepthEnable)
291 	, m_defaultDepthValue	(defaultDepth)
292 	, m_depthClampEnable	(depthClampEnable)
293 	, m_samples				(samples)
294 	, m_renderSize			(RENDERWIDTH, RENDERHEIGHT)
295 	, m_largeDepthBase		(20.0f)
296 {
297 	const InstanceInterface&	vki					= m_context.getInstanceInterface();
298 	const VkPhysicalDevice		physicalDevice		= m_context.getPhysicalDevice();
299 
300 	try
301 	{
302 		VkImageFormatProperties		imageFormatProperties;
303 		VkFormatProperties			formatProperties;
304 
305 		if (m_context.getDeviceFeatures().fragmentStoresAndAtomics == VK_FALSE)
306 			throw tcu::NotSupportedError("fragmentStoresAndAtomics not supported");
307 
308 		imageFormatProperties = getPhysicalDeviceImageFormatProperties(vki, physicalDevice, m_format, VK_IMAGE_TYPE_2D,
309 				VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, (VkImageCreateFlags)0);
310 
311 		if ((imageFormatProperties.sampleCounts & m_samples) == 0)
312 			throw tcu::NotSupportedError("Image format and sample count not supported");
313 
314 		formatProperties = getPhysicalDeviceFormatProperties(vki, physicalDevice, VK_FORMAT_R8G8B8A8_UINT);
315 
316 		if ((formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) == 0)
317 			throw tcu::NotSupportedError("MarkerImage format not supported as storage image");
318 
319 		if (m_largeDepthEnable && !de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_EXT_depth_range_unrestricted"))
320 			throw tcu::NotSupportedError("large_depth test variants require the VK_EXT_depth_range_unrestricted extension");
321 
322 		if (m_context.getDeviceFeatures().depthClamp == VK_FALSE && m_depthClampEnable)
323 			throw tcu::NotSupportedError("Depthclamp is not supported.");
324 	}
325 	catch (const vk::Error& e)
326 	{
327 		if (e.getError() == VK_ERROR_FORMAT_NOT_SUPPORTED)
328 			throw tcu::NotSupportedError("Image format not supported");
329 		else
330 			throw;
331 
332 	}
333 }
334 
iterate(void)335 TestStatus BuiltinFragDepthCaseInstance::iterate (void)
336 {
337 	const VkDevice					device				= m_context.getDevice();
338 	const DeviceInterface&			vk					= m_context.getDeviceInterface();
339 	const VkQueue					queue				= m_context.getUniversalQueue();
340 	Allocator&						allocator			= m_context.getDefaultAllocator();
341 	const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
342 	TestLog&						log					= m_context.getTestContext().getLog();
343 	const deUint32					scale				= 4;										// To account for std140 stride
344 	const VkDeviceSize				pixelCount			= m_renderSize.x() * m_renderSize.y();
345 	std::string						testDesc;
346 	Move<VkImage>					depthResolveImage;
347 	Move<VkImageView>				depthResolveImageView;
348 	MovePtr<Allocation>				depthResolveAllocation;
349 	Move<VkImage>					depthImage;
350 	Move<VkImageView>				depthImageView;
351 	MovePtr<Allocation>				depthImageAllocation;
352 	Move<VkBuffer>					controlBuffer;
353 	MovePtr<Allocation>				controlBufferAllocation;
354 	Move<VkImage>					markerImage;
355 	Move<VkImageView>				markerImageView;
356 	MovePtr<Allocation>				markerImageAllocation;
357 	Move<VkBuffer>					markerBuffer;
358 	MovePtr<Allocation>				markerBufferAllocation;
359 	Move<VkBuffer>					validationBuffer;
360 	MovePtr<Allocation>				validationAlloc;
361 	MovePtr<Allocation>				depthInitAllocation;
362 	Move<VkCommandPool>				cmdPool;
363 	Move<VkCommandBuffer>			transferCmdBuffer;
364 	Move<VkSampler>					depthSampler;
365 
366 	// Create Buffer/Image for validation
367 	{
368 		VkFormat	resolvedBufferFormat = VK_FORMAT_R32_SFLOAT;
369 		const VkBufferCreateInfo validationBufferCreateInfo =
370 		{
371 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,										// VkStructureType		sType
372 			DE_NULL,																	// const void*			pNext
373 			(VkBufferCreateFlags)0,														// VkBufferCreateFlags	flags
374 			m_samples * pixelCount * getPixelSize(mapVkFormat(resolvedBufferFormat)),	// VkDeviceSize			size
375 			VK_BUFFER_USAGE_TRANSFER_DST_BIT,											// VkBufferUsageFlags	usage
376 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode		sharingMode
377 			0u,																			// uint32_t				queueFamilyIndexCount,
378 			DE_NULL																		// const uint32_t*		pQueueFamilyIndices
379 		};
380 
381 		validationBuffer = createBuffer(vk, device, &validationBufferCreateInfo);
382 		validationAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *validationBuffer), MemoryRequirement::HostVisible);
383 		VK_CHECK(vk.bindBufferMemory(device, *validationBuffer, validationAlloc->getMemory(), validationAlloc->getOffset()));
384 
385 		const VkImageCreateInfo depthResolveImageCreateInfo =
386 		{
387 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,								// VkStructureType			sType
388 			DE_NULL,															// const void*				pNext
389 			(VkImageCreateFlags)0,												// VkImageCreateFlags		flags
390 			VK_IMAGE_TYPE_2D,													// VkIMageType				imageType
391 			resolvedBufferFormat,												// VkFormat					format
392 			makeExtent3D(m_samples * m_renderSize.x(), m_renderSize.y(), 1u),	// VkExtent3D				extent
393 			1u,																	// uint32_t					mipLevels
394 			1u,																	// uint32_t					arrayLayers
395 			VK_SAMPLE_COUNT_1_BIT,												// VkSampleCountFlagsBits	samples
396 			VK_IMAGE_TILING_OPTIMAL,											// VkImageTiling			tiling
397 			VK_IMAGE_USAGE_TRANSFER_SRC_BIT |									// VkImageUsageFlags		usage
398 			VK_IMAGE_USAGE_STORAGE_BIT |
399 			VK_IMAGE_USAGE_TRANSFER_DST_BIT,
400 			VK_SHARING_MODE_EXCLUSIVE,											// VkSharingMode			sharingMode
401 			0u,																	// uint32_t					queueFamilyIndexCount
402 			DE_NULL,															// const uint32_t			pQueueFamilyIndices
403 			VK_IMAGE_LAYOUT_UNDEFINED											// VkImageLayout			initialLayout
404 		};
405 
406 		depthResolveImage = createImage(vk, device, &depthResolveImageCreateInfo, DE_NULL);
407 		depthResolveAllocation = allocator.allocate(getImageMemoryRequirements(vk, device, *depthResolveImage), MemoryRequirement::Any);
408 		VK_CHECK(vk.bindImageMemory(device, *depthResolveImage, depthResolveAllocation->getMemory(), depthResolveAllocation->getOffset()));
409 
410 		const VkImageViewCreateInfo depthResolveImageViewCreateInfo =
411 		{
412 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,								// VkStructureType			sType
413 			DE_NULL,																// const void*				pNext
414 			(VkImageViewCreateFlags)0,												// VkImageViewCreateFlags	flags
415 			*depthResolveImage,														// VkImage					image
416 			VK_IMAGE_VIEW_TYPE_2D,													// VkImageViewType			type
417 			resolvedBufferFormat,													// VkFormat					format
418 			makeComponentMappingRGBA(),												// VkComponentMapping		componentMapping
419 			makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)	// VkImageSUbresourceRange	subresourceRange
420 		};
421 
422 		depthResolveImageView = createImageView(vk, device, &depthResolveImageViewCreateInfo, DE_NULL);
423 	}
424 
425 	// Marker Buffer
426 	{
427 		const VkDeviceSize	size			= m_samples * m_renderSize.x() * m_renderSize.y() * getPixelSize(mapVkFormat(VK_FORMAT_R8G8B8A8_UINT));
428 
429 		const VkBufferCreateInfo markerBufferCreateInfo =
430 		{
431 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,			// VkStructureType			sType
432 			DE_NULL,										// const void*				pNext
433 			(VkBufferCreateFlags)0,							// VkBufferCreateFlags		flags
434 			size,											// VkDeviceSize				size
435 			VK_BUFFER_USAGE_TRANSFER_DST_BIT,				// VkBufferUsageFlags		usage
436 			VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode
437 			0u,												// uint32_t					queueFamilyIndexCount
438 			DE_NULL											// const uint32_t*			pQueueFamilyIndices
439 		};
440 
441 		markerBuffer = createBuffer(vk, device, &markerBufferCreateInfo, DE_NULL);
442 		markerBufferAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *markerBuffer), MemoryRequirement::HostVisible);
443 		VK_CHECK(vk.bindBufferMemory(device, *markerBuffer, markerBufferAllocation->getMemory(), markerBufferAllocation->getOffset()));
444 
445 		const VkImageCreateInfo markerImageCreateInfo =
446 		{
447 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,							// VkStructureType			sType
448 			DE_NULL,														// const void*				pNext
449 			(VkImageCreateFlags)0,											// VkImageCreateFlags		flags
450 			VK_IMAGE_TYPE_2D,												// VkImageType				imageType
451 			VK_FORMAT_R8G8B8A8_UINT,										// VkFormat					format
452 			makeExtent3D(m_samples * m_renderSize.x(), m_renderSize.y(), 1),// VkExtent3D				extent
453 			1u,																// uint32_t					mipLevels
454 			1u,																// uint32_t					arrayLayers
455 			VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagsBit	smaples
456 			VK_IMAGE_TILING_OPTIMAL,										// VkImageTiling			tiling
457 			VK_IMAGE_USAGE_STORAGE_BIT |									// VkImageUsageFlags		usage
458 			VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
459 			VK_IMAGE_USAGE_TRANSFER_DST_BIT,
460 			VK_SHARING_MODE_EXCLUSIVE,										// VkSharingMode			sharing
461 			0u,																// uint32_t					queueFamilyIndexCount
462 			DE_NULL,														// const uint32_t*			pQueueFamilyIndices
463 			VK_IMAGE_LAYOUT_UNDEFINED										// VkImageLayout			initialLayout
464 		};
465 
466 		markerImage = createImage(vk, device, &markerImageCreateInfo, DE_NULL);
467 		markerImageAllocation = allocator.allocate(getImageMemoryRequirements(vk, device, *markerImage), MemoryRequirement::Any);
468 		VK_CHECK(vk.bindImageMemory(device, *markerImage, markerImageAllocation->getMemory(), markerImageAllocation->getOffset()));
469 
470 		const VkImageViewCreateInfo markerViewCreateInfo =
471 		{
472 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,				// VkStructureType			sType
473 			DE_NULL,												// const void*				pNext
474 			(VkImageViewCreateFlags)0,								// VkImageViewCreateFlags	flags
475 			*markerImage,											// VkImage					image
476 			VK_IMAGE_VIEW_TYPE_2D,									// VkImageViewType			viewType
477 			VK_FORMAT_R8G8B8A8_UINT,								// VkFormat					format
478 			makeComponentMappingRGBA(),								// VkComponentMapping		components
479 			makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)
480 		};
481 
482 		markerImageView = createImageView(vk, device, &markerViewCreateInfo, DE_NULL);
483 	}
484 
485 	// Control Buffer
486 	{
487 		const VkBufferCreateInfo controlBufferCreateInfo =
488 		{
489 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,					// VkStructureType		sType
490 			DE_NULL,												// const void*			pNext
491 			(VkBufferCreateFlags)0,									// VkBufferCreateFlags	flags
492 			pixelCount * sizeof(float)* scale,						// VkDeviceSize			size
493 			VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,						// VkBufferUsageFlags	usage
494 			VK_SHARING_MODE_EXCLUSIVE,								// VkSharingMode		sharingMode
495 			0u,														// deUint32				queueFamilyIndexCount
496 
497 			DE_NULL													// pQueueFamilyIndices
498 		};
499 
500 		controlBuffer = createBuffer(vk, device, &controlBufferCreateInfo, DE_NULL);
501 		controlBufferAllocation = allocator.allocate( getBufferMemoryRequirements(vk, device, *controlBuffer), MemoryRequirement::HostVisible);
502 		VK_CHECK(vk.bindBufferMemory(device, *controlBuffer, controlBufferAllocation->getMemory(), controlBufferAllocation->getOffset()));
503 
504 		{
505 			float* bufferData = (float*)(controlBufferAllocation->getHostPtr());
506 			float sign = m_depthClampEnable ? -1.0f : 1.0f;
507 			for (deUint32 ndx = 0; ndx < m_renderSize.x() * m_renderSize.y(); ndx++)
508 			{
509 				bufferData[ndx * scale] = (float)ndx / 256.0f * sign;
510 				if (m_largeDepthEnable)
511 					bufferData[ndx * scale] += m_largeDepthBase;
512 			}
513 
514 			const VkMappedMemoryRange range =
515 			{
516 				VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
517 				DE_NULL,
518 				controlBufferAllocation->getMemory(),
519 				0u,
520 				VK_WHOLE_SIZE
521 			};
522 
523 			VK_CHECK(vk.flushMappedMemoryRanges(device, 1u, &range));
524 		}
525 	}
526 
527 	// Depth Buffer
528 	{
529 		VkImageSubresourceRange depthSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u);
530 		const VkImageCreateInfo depthImageCreateInfo	=
531 		{
532 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,					// VkStructureType			sType
533 			DE_NULL,												// const void*				pNext
534 			(VkImageCreateFlags)0,									// VkImageCreateFlags		flags
535 			VK_IMAGE_TYPE_2D,										// VkImageType				imageType
536 			m_format,												// VkFormat					format
537 			makeExtent3D(m_renderSize.x(), m_renderSize.y(), 1u),	// VkExtent3D				extent
538 			1u,														// uint32_t					mipLevels
539 			1u,														// uint32_t					arrayLayers
540 			m_samples,												// VkSampleCountFlagsBits	samples
541 			VK_IMAGE_TILING_OPTIMAL,								// VkImageTiling			tiling
542 			VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
543 			VK_IMAGE_USAGE_TRANSFER_DST_BIT |
544 			VK_IMAGE_USAGE_SAMPLED_BIT      |
545 			VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,			// VkImageUsageFlags		usage
546 			VK_SHARING_MODE_EXCLUSIVE,								// VkShaderingMode			sharingMode
547 			0u,														// uint32_t					queueFamilyIndexCount
548 			DE_NULL,												// const uint32_t*			pQueueFamilyIndices
549 			VK_IMAGE_LAYOUT_UNDEFINED								// VkImageLayout			initialLayout
550 		};
551 
552 		depthImage = createImage(vk, device, &depthImageCreateInfo, DE_NULL);
553 		depthImageAllocation = allocator.allocate(getImageMemoryRequirements(vk, device, *depthImage), MemoryRequirement::Any);
554 		VK_CHECK(vk.bindImageMemory(device, *depthImage, depthImageAllocation->getMemory(), depthImageAllocation->getOffset()));
555 
556 		const VkImageViewCreateInfo imageViewParams =
557 		{
558 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
559 			DE_NULL,										// const void*				pNext;
560 			(VkImageViewCreateFlags)0,						// VkImageViewCreateFlags	flags;
561 			*depthImage,									// VkImage					image;
562 			VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType			viewType;
563 			m_format,										// VkFormat					format;
564 			makeComponentMappingRGBA(),						// VkComponentMapping		components;
565 			depthSubresourceRange,							// VkImageSubresourceRange	subresourceRange;
566 		};
567 		depthImageView = createImageView(vk, device, &imageViewParams);
568 
569 		const VkSamplerCreateInfo depthSamplerCreateInfo =
570 		{
571 			VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,			// VkStructureType			sType
572 			DE_NULL,										// const void*				pNext
573 			(VkSamplerCreateFlags)0,						// VkSamplerCreateFlags		flags
574 			VK_FILTER_NEAREST,								// VkFilter					minFilter
575 			VK_FILTER_NEAREST,								// VkFilter					magFilter
576 			VK_SAMPLER_MIPMAP_MODE_NEAREST,					// VkSamplerMipMapMode		mipMapMode
577 			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			// VkSamplerAddressMode		addressModeU
578 			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			// VkSamplerAddressMode		addressModeV
579 			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			// VkSamplerAddressMode		addressmodeW
580 			0.0f,											// float					mipLodBias
581 			VK_FALSE,										// VkBool32					anisotropyEnable
582 			0.0f,											// float					maxAnisotropy
583 			VK_FALSE,										// VkBool32					compareEnable
584 			VK_COMPARE_OP_NEVER,							// VkCompareOp				compareOp
585 			0.0f,											// float					minLod
586 			0.0f,											// float					maxLod
587 			VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,		// VkBorderColor			borderColor
588 			VK_FALSE										// VkBool32					unnormalizedCoordinates
589 		};
590 
591 		depthSampler = createSampler(vk, device, &depthSamplerCreateInfo, DE_NULL);
592 	}
593 
594 	// Command Pool
595 	{
596 		const VkCommandPoolCreateInfo cmdPoolCreateInfo =
597 		{
598 			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,			// VkStructureType			sType
599 			DE_NULL,											// const void*				pNext
600 			VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,	// VkCommandPoolCreateFlags	flags
601 			queueFamilyIndex									// uint32_t					queueFamilyIndex
602 		};
603 
604 		cmdPool = createCommandPool(vk, device, &cmdPoolCreateInfo);
605 	}
606 
607 	// Command buffer for data transfers
608 	{
609 		const VkCommandBufferAllocateInfo cmdBufferAllocInfo =
610 		{
611 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType		sType,
612 			DE_NULL,										// const void*			pNext
613 			*cmdPool,										// VkCommandPool		commandPool
614 			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel	level
615 			1u												// uint32_t				bufferCount
616 		};
617 
618 		transferCmdBuffer = allocateCommandBuffer(vk, device, &cmdBufferAllocInfo);
619 	}
620 
621 	// Initialize Marker Buffer
622 	{
623 		VkImageAspectFlags	depthImageAspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT;
624 		if (hasStencilComponent(mapVkFormat(m_format).order))
625 			depthImageAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
626 
627 		const VkImageMemoryBarrier imageBarrier[] =
628 		{
629 			{
630 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType		sType
631 				DE_NULL,										// const void*			pNext
632 				0,												// VkAccessMask			srcAccessMask
633 				VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessMask			dstAccessMask
634 				VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout		oldLayout
635 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout		newLayout
636 				VK_QUEUE_FAMILY_IGNORED,						// uint32_t				srcQueueFamilyIndex
637 				VK_QUEUE_FAMILY_IGNORED,						// uint32_t				dstQueueFamilyIndex
638 				*markerImage,									// VkImage				image
639 				{
640 					VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask
641 					0u,										// uint32_t				baseMipLevel
642 					1u,										// uint32_t				mipLevels
643 					0u,										// uint32_t				baseArray
644 					1u										// uint32_t				arraySize
645 				}
646 			},
647 		};
648 
649 		const VkImageMemoryBarrier imagePostBarrier[] =
650 		{
651 			{
652 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType		sType
653 				DE_NULL,										// const void*			pNext
654 				VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlagBits		srcAccessMask
655 				VK_ACCESS_SHADER_WRITE_BIT,						// VkAccessFlagBits		dstAccessMask
656 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout		oldLayout
657 				VK_IMAGE_LAYOUT_GENERAL,						// VkImageLayout		newLayout
658 				VK_QUEUE_FAMILY_IGNORED,						// uint32_t				srcQueueFamilyIndex
659 				VK_QUEUE_FAMILY_IGNORED,						// uint32_t				dstQueueFamilyIndex
660 				*markerImage,									// VkImage				image
661 				{
662 					VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask
663 					0u,										// uint32_t				baseMipLevel
664 					1u,										// uint32_t				mipLevels
665 					0u,										// uint32_t				baseArray
666 					1u										// uint32_t				arraySize
667 				}
668 			},
669 		};
670 
671 		beginCommandBuffer(vk, *transferCmdBuffer);
672 		vk.cmdPipelineBarrier(*transferCmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
673 				(VkDependencyFlags)0,
674 				0, (const VkMemoryBarrier*)DE_NULL,
675 				0, (const VkBufferMemoryBarrier*)DE_NULL,
676 				DE_LENGTH_OF_ARRAY(imageBarrier), imageBarrier);
677 
678 		const VkClearValue				colorClearValue	= makeClearValueColor(Vec4(0.0f, 0.0f, 0.0f, 0.0f));
679 		const VkImageSubresourceRange	colorClearRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
680 
681 		vk.cmdClearColorImage(*transferCmdBuffer, *markerImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &colorClearValue.color, 1u, &colorClearRange);
682 
683 		vk.cmdPipelineBarrier(*transferCmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
684 				(VkDependencyFlags)0,
685 				0, (const VkMemoryBarrier*)DE_NULL,
686 				0, (const VkBufferMemoryBarrier*)DE_NULL,
687 				DE_LENGTH_OF_ARRAY(imagePostBarrier), imagePostBarrier);
688 
689 		endCommandBuffer(vk, *transferCmdBuffer);
690 
691 		submitCommandsAndWait(vk, device, queue, transferCmdBuffer.get());
692 	}
693 
694 
695 	// Perform Draw
696 	{
697 		std::vector<Vec4>				vertices;
698 		std::vector<VulkanShader>		shaders;
699 		Move<VkDescriptorSetLayout>		descriptorSetLayout;
700 		Move<VkDescriptorPool>			descriptorPool;
701 		Move<VkDescriptorSet>			descriptorSet;
702 
703 		// Descriptors
704 		{
705 			DescriptorSetLayoutBuilder	layoutBuilder;
706 			layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT);
707 			layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT);
708 			descriptorSetLayout = layoutBuilder.build(vk, device);
709 			descriptorPool = DescriptorPoolBuilder()
710 					.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
711 					.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
712 					.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
713 
714 			const VkDescriptorSetAllocateInfo descriptorSetAllocInfo =
715 			{
716 				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
717 				DE_NULL,
718 				*descriptorPool,
719 				1u,
720 				&descriptorSetLayout.get()
721 			};
722 
723 			descriptorSet = allocateDescriptorSet(vk, device, &descriptorSetAllocInfo);
724 
725 			const VkDescriptorBufferInfo bufferInfo =
726 			{
727 				*controlBuffer,
728 				0u,
729 				VK_WHOLE_SIZE
730 			};
731 
732 			const VkDescriptorImageInfo imageInfo =
733 			{
734 				(VkSampler)DE_NULL,
735 				*markerImageView,
736 				VK_IMAGE_LAYOUT_GENERAL
737 			};
738 
739 			DescriptorSetUpdateBuilder()
740 				.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufferInfo)
741 				.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageInfo)
742 				.update(vk, device);
743 		}
744 
745 		vertices.push_back(Vec4( -0.70f,	0.5f,	0.0f,	1.0f));
746 		vertices.push_back(Vec4(  0.45f,	-0.75f,	0.0f,	1.0f));
747 		vertices.push_back(Vec4(  0.78f,	0.0f,	0.0f,	1.0f));
748 		vertices.push_back(Vec4( -0.1f,		0.6f,	0.0f,	1.0f));
749 
750 		shaders.push_back(VulkanShader(VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("FragDepthVert")));
751 		shaders.push_back(VulkanShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("FragDepthFrag")));
752 
753 		DrawState				drawState(m_topology, m_renderSize.x(), m_renderSize.y());
754 		DrawCallData			drawCallData(vertices);
755 		VulkanProgram			vulkanProgram(shaders);
756 
757 		drawState.depthClampEnable			= m_depthClampEnable;
758 		drawState.depthFormat				= m_format;
759 		drawState.numSamples				= m_samples;
760 		drawState.compareOp					= rr::TESTFUNC_ALWAYS;
761 		drawState.depthTestEnable			= true;
762 		drawState.depthWriteEnable			= true;
763 		drawState.sampleShadingEnable		= true;
764 		vulkanProgram.depthImageView		= *depthImageView;
765 		vulkanProgram.descriptorSetLayout	= *descriptorSetLayout;
766 		vulkanProgram.descriptorSet			= *descriptorSet;
767 
768 		VulkanDrawContext		vulkanDrawContext(m_context, drawState, drawCallData, vulkanProgram);
769 		vulkanDrawContext.draw();
770 
771 		log << TestLog::Image(	"resultColor",
772 								"Result Color Buffer",
773 								tcu::ConstPixelBufferAccess(tcu::TextureFormat(
774 										vulkanDrawContext.getColorPixels().getFormat()),
775 										vulkanDrawContext.getColorPixels().getWidth(),
776 										vulkanDrawContext.getColorPixels().getHeight(),
777 										1,
778 										vulkanDrawContext.getColorPixels().getDataPtr()));
779 	}
780 
781 	// Barrier to transition between first and second pass
782 	{
783 		VkImageAspectFlags	depthImageAspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT;
784 		if (hasStencilComponent(mapVkFormat(m_format).order))
785 			depthImageAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
786 
787 		const VkImageMemoryBarrier imageBarrier[] =
788 		{
789 			{
790 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,						// VkStructureType		sType
791 				DE_NULL,													// const void*			pNext
792 				VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,				// VkAccessFlags		srcAccessMask
793 				VK_ACCESS_SHADER_READ_BIT,									// VkAccessFlags		dstAccessMask
794 				VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,			// VkImageLayout		oldLayout
795 				VK_IMAGE_LAYOUT_GENERAL,									// VkImageLayout		newLayout
796 				0u,															// deUint32				srcQueueFamilyIndex
797 				0u,															// deUint32				dstQueueFamilyIndex
798 				*depthImage,												// VkImage				image
799 				{
800 					depthImageAspectFlags,							// VkImageAspectFlags		aspectMask
801 					0u,												// deUint32					baseMipLevel
802 					1u,												// deUint32					levelCount
803 					0u,												// deUint32					baseArrayLayer
804 					1u												// deUint32					layerCount
805 				}
806 			},
807 			{
808 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,						// VkStructureType		sType
809 				DE_NULL,													// const void*			pNext
810 				0u,															// VkAccessFlags		srcAccessMask
811 				VK_ACCESS_HOST_READ_BIT,									// VkAccessFlags		dstAccessMask
812 				VK_IMAGE_LAYOUT_UNDEFINED,									// VkImageLayout		oldLayout
813 				VK_IMAGE_LAYOUT_GENERAL,									// VkImageLayout		newLayout
814 				0u,															// deUint32				srcQueueFamilyIndex
815 				0u,															// deUint32				dstQueueFamilyIndex
816 				*depthResolveImage,											// VkImage				image
817 				{
818 					VK_IMAGE_ASPECT_COLOR_BIT,						// VkImageAspectFlags		aspectMask
819 					0u,												// deUint32					baseMipLevel
820 					1u,												// deUint32					levelCount
821 					0u,												// deUint32					baseArrayLayer
822 					1u,												// deUint32					layerCount
823 
824 				}
825 			}
826 		};
827 
828 		beginCommandBuffer(vk, *transferCmdBuffer);
829 		vk.cmdPipelineBarrier(*transferCmdBuffer, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_HOST_BIT,
830 				(VkDependencyFlags)0,
831 				0, (const VkMemoryBarrier*)DE_NULL,
832 				0, (const VkBufferMemoryBarrier*)DE_NULL,
833 				DE_LENGTH_OF_ARRAY(imageBarrier), imageBarrier);
834 		endCommandBuffer(vk, *transferCmdBuffer);
835 
836 		submitCommandsAndWait(vk, device, queue, transferCmdBuffer.get());
837 	}
838 
839 	// Resolve Depth Buffer
840 	{
841 		std::vector<Vec4>				vertices;
842 		std::vector<VulkanShader>		shaders;
843 		Move<VkDescriptorSetLayout>		descriptorSetLayout;
844 		Move<VkDescriptorPool>			descriptorPool;
845 		Move<VkDescriptorSet>			descriptorSet;
846 
847 		// Descriptors
848 		{
849 			DescriptorSetLayoutBuilder	layoutBuilder;
850 			layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
851 			layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT);
852 			descriptorSetLayout = layoutBuilder.build(vk, device);
853 			descriptorPool = DescriptorPoolBuilder()
854 					.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
855 					.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
856 					.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
857 
858 			const VkDescriptorSetAllocateInfo descriptorSetAllocInfo =
859 			{
860 				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
861 				DE_NULL,
862 				*descriptorPool,
863 				1u,
864 				&descriptorSetLayout.get()
865 			};
866 
867 			descriptorSet = allocateDescriptorSet(vk, device, &descriptorSetAllocInfo);
868 
869 			const VkDescriptorImageInfo depthImageInfo =
870 			{
871 				*depthSampler,
872 				*depthImageView,
873 				VK_IMAGE_LAYOUT_GENERAL
874 			};
875 
876 			const VkDescriptorImageInfo imageInfo =
877 			{
878 				(VkSampler)DE_NULL,
879 				*depthResolveImageView,
880 				VK_IMAGE_LAYOUT_GENERAL
881 			};
882 
883 			DescriptorSetUpdateBuilder()
884 				.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &depthImageInfo)
885 				.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageInfo)
886 				.update(vk, device);
887 		}
888 
889 		vertices.push_back(Vec4( -1.0f,	-1.0f,	0.0f,	1.0f));
890 		vertices.push_back(Vec4( -1.0f,	 1.0f,	0.0f,	1.0f));
891 		vertices.push_back(Vec4(  1.0f,	-1.0f,	0.0f,	1.0f));
892 		vertices.push_back(Vec4(  1.0f,	 1.0f,	0.0f,	1.0f));
893 
894 		shaders.push_back(VulkanShader(VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("FragDepthVertPass2")));
895 		shaders.push_back(VulkanShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("FragDepthFragPass2")));
896 
897 		DrawState				drawState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, m_renderSize.x(), m_renderSize.y());
898 		DrawCallData			drawCallData(vertices);
899 		VulkanProgram			vulkanProgram(shaders);
900 
901 		drawState.numSamples				= m_samples;
902 		drawState.sampleShadingEnable		= true;
903 		vulkanProgram.descriptorSetLayout	= *descriptorSetLayout;
904 		vulkanProgram.descriptorSet			= *descriptorSet;
905 
906 		VulkanDrawContext		vulkanDrawContext(m_context, drawState, drawCallData, vulkanProgram);
907 		vulkanDrawContext.draw();
908 	}
909 
910 	// Transfer marker buffer
911 	{
912 		beginCommandBuffer(vk, *transferCmdBuffer);
913 		copyImageToBuffer(vk, *transferCmdBuffer, *markerImage, *markerBuffer, tcu::IVec2(m_renderSize.x() * m_samples, m_renderSize.y()), VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
914 		endCommandBuffer(vk, *transferCmdBuffer);
915 
916 		submitCommandsAndWait(vk, device, queue, transferCmdBuffer.get());
917 	}
918 
919 	// Verify depth buffer
920 	{
921 		bool status;
922 
923 		beginCommandBuffer(vk, *transferCmdBuffer, 0u);
924 		copyImageToBuffer(vk, *transferCmdBuffer, *depthResolveImage, *validationBuffer, tcu::IVec2(m_renderSize.x() * m_samples, m_renderSize.y()), VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
925 		endCommandBuffer(vk, *transferCmdBuffer);
926 
927 		submitCommandsAndWait(vk, device, queue, transferCmdBuffer.get());
928 
929 		invalidateMappedMemoryRange(vk, device, validationAlloc->getMemory(), validationAlloc->getOffset(), VK_WHOLE_SIZE);
930 		invalidateMappedMemoryRange(vk, device, markerBufferAllocation->getMemory(), markerBufferAllocation->getOffset(), VK_WHOLE_SIZE);
931 
932 		tcu::ConstPixelBufferAccess resultPixelBuffer(mapVkFormat(VK_FORMAT_R32_SFLOAT), m_renderSize.x() * m_samples, m_renderSize.y(), 1u, validationAlloc->getHostPtr());
933 		tcu::ConstPixelBufferAccess markerPixelBuffer(mapVkFormat(VK_FORMAT_R8G8B8A8_UINT), m_renderSize.x() * m_samples, m_renderSize.y(), 1u, markerBufferAllocation->getHostPtr());
934 		status = validateDepthBuffer(resultPixelBuffer, markerPixelBuffer, 0.001f);
935 		testDesc = "gl_FragDepth " + getPrimitiveTopologyShortName(m_topology) + " ";
936 		if (status)
937 		{
938 			testDesc += "passed";
939 			return tcu::TestStatus::pass(testDesc.c_str());
940 		}
941 		else
942 		{
943 			log << TestLog::Image("resultDepth", "Result Depth Buffer", resultPixelBuffer);
944 			testDesc += "failed";
945 			return tcu::TestStatus::fail(testDesc.c_str());
946 		}
947 	}
948 }
949 
validateDepthBuffer(const tcu::ConstPixelBufferAccess & validationBuffer,const tcu::ConstPixelBufferAccess & markerBuffer,const float tolerance) const950 bool BuiltinFragDepthCaseInstance::validateDepthBuffer (const tcu::ConstPixelBufferAccess& validationBuffer, const tcu::ConstPixelBufferAccess& markerBuffer, const float tolerance) const
951 {
952 	TestLog& log = m_context.getTestContext().getLog();
953 
954 	for (deUint32 rowNdx = 0; rowNdx < m_renderSize.y(); rowNdx++)
955 	{
956 		for (deUint32 colNdx = 0; colNdx < m_renderSize.x(); colNdx++)
957 		{
958 			const float multiplier		= m_depthClampEnable ? 0.0f : 1.0f;
959 			float expectedValue	= (float)(rowNdx * m_renderSize.x() + colNdx)/256.0f * multiplier;
960 
961 			if (m_largeDepthEnable)
962 				expectedValue += m_largeDepthBase;
963 
964 			for (deUint32 sampleNdx = 0; sampleNdx < (deUint32)m_samples; sampleNdx++)
965 			{
966 				const float	actualValue		= validationBuffer.getPixel(sampleNdx + m_samples * colNdx, rowNdx).x();
967 				const float	markerValue		= markerBuffer.getPixel(sampleNdx + m_samples * colNdx, rowNdx).x();
968 
969 				if (markerValue != 0)
970 				{
971 					if (de::abs(expectedValue - actualValue) > tolerance)
972 					{
973 						log << TestLog::Message << "Mismatch at pixel (" << colNdx << "," << rowNdx << "," << sampleNdx << "): expected " << expectedValue << " but got " << actualValue << TestLog::EndMessage;
974 						return false;
975 					}
976 				}
977 				else
978 				{
979 					if (de::abs(actualValue - m_defaultDepthValue) > tolerance)
980 					{
981 						log << TestLog::Message << "Mismatch at pixel (" << colNdx << "," << rowNdx << "," << sampleNdx << "): expected " << expectedValue << " but got " << actualValue << TestLog::EndMessage;
982 						return false;
983 					}
984 				}
985 			}
986 		}
987 	}
988 
989 	return true;
990 }
991 
992 class BuiltinFragCoordMsaaCaseInstance : public TestInstance
993 {
994 public:
995 	enum
996 	{
997 		RENDERWIDTH		= 16,
998 		RENDERHEIGHT	= 16
999 	};
1000 				BuiltinFragCoordMsaaCaseInstance	(Context& context, VkSampleCountFlagBits sampleCount);
1001 	TestStatus	iterate								(void);
1002 private:
1003 	bool		validateSampleLocations				(const ConstPixelBufferAccess& sampleLocationBuffer) const;
1004 
1005 	const tcu::UVec2				m_renderSize;
1006 	const VkSampleCountFlagBits		m_sampleCount;
1007 };
1008 
BuiltinFragCoordMsaaCaseInstance(Context & context,VkSampleCountFlagBits sampleCount)1009 BuiltinFragCoordMsaaCaseInstance::BuiltinFragCoordMsaaCaseInstance (Context& context, VkSampleCountFlagBits sampleCount)
1010 	: TestInstance		(context)
1011 	, m_renderSize		(RENDERWIDTH, RENDERHEIGHT)
1012 	, m_sampleCount		(sampleCount)
1013 {
1014 	const InstanceInterface&	vki					= m_context.getInstanceInterface();
1015 	const VkPhysicalDevice		physicalDevice		= m_context.getPhysicalDevice();
1016 
1017 	try
1018 	{
1019 		VkImageFormatProperties		imageFormatProperties;
1020 		VkFormatProperties			formatProperties;
1021 
1022 		if (m_context.getDeviceFeatures().fragmentStoresAndAtomics == VK_FALSE)
1023 			throw tcu::NotSupportedError("fragmentStoresAndAtomics not supported");
1024 
1025 		imageFormatProperties = getPhysicalDeviceImageFormatProperties(vki, physicalDevice, VK_FORMAT_R32G32B32A32_SFLOAT, VK_IMAGE_TYPE_2D,
1026 				VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, (VkImageCreateFlags)0);
1027 
1028 		if ((imageFormatProperties.sampleCounts & m_sampleCount) == 0)
1029 			throw tcu::NotSupportedError("Image format and sample count not supported");
1030 
1031 		formatProperties = getPhysicalDeviceFormatProperties(vki, physicalDevice, VK_FORMAT_R32G32B32A32_SFLOAT);
1032 
1033 		if ((formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) == 0)
1034 			throw tcu::NotSupportedError("Output format not supported as storage image");
1035 	}
1036 	catch (const vk::Error& e)
1037 	{
1038 		if (e.getError() == VK_ERROR_FORMAT_NOT_SUPPORTED)
1039 			throw tcu::NotSupportedError("Image format not supported");
1040 		else
1041 			throw;
1042 
1043 	}
1044 }
1045 
iterate(void)1046 TestStatus BuiltinFragCoordMsaaCaseInstance::iterate (void)
1047 {
1048 	const VkDevice					device				= m_context.getDevice();
1049 	const DeviceInterface&			vk					= m_context.getDeviceInterface();
1050 	const VkQueue					queue				= m_context.getUniversalQueue();
1051 	Allocator&						allocator			= m_context.getDefaultAllocator();
1052 	const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1053 	TestLog&						log					= m_context.getTestContext().getLog();
1054 	Move<VkImage>					outputImage;
1055 	Move<VkImageView>				outputImageView;
1056 	MovePtr<Allocation>				outputImageAllocation;
1057 	Move<VkDescriptorSetLayout>		descriptorSetLayout;
1058 	Move<VkDescriptorPool>			descriptorPool;
1059 	Move<VkDescriptorSet>			descriptorSet;
1060 	Move<VkBuffer>					sampleLocationBuffer;
1061 	MovePtr<Allocation>				sampleLocationBufferAllocation;
1062 	Move<VkCommandPool>				cmdPool;
1063 	Move<VkCommandBuffer>			transferCmdBuffer;
1064 
1065 	// Coordinate result image
1066 	{
1067 		const VkImageCreateInfo outputImageCreateInfo =
1068 		{
1069 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,					// VkStructureType			sType
1070 			DE_NULL,												// const void*				pNext
1071 			(VkImageCreateFlags)0,									// VkImageCreateFlags		flags
1072 			VK_IMAGE_TYPE_2D,										// VkImageType				imageType
1073 			VK_FORMAT_R32G32B32A32_SFLOAT,							// VkFormat					format
1074 			makeExtent3D(m_sampleCount * m_renderSize.x(), m_renderSize.y(), 1u),	// VkExtent3D				extent3d
1075 			1u,														// uint32_t					mipLevels
1076 			1u,														// uint32_t					arrayLayers
1077 			VK_SAMPLE_COUNT_1_BIT,									// VkSampleCountFlagBits	samples
1078 			VK_IMAGE_TILING_OPTIMAL,								// VkImageTiling			tiling
1079 			VK_IMAGE_USAGE_STORAGE_BIT |							// VkImageUsageFlags		usage
1080 			VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
1081 			VK_SHARING_MODE_EXCLUSIVE,								// VkSharingMode			sharingMode
1082 			0u,														// uint32_t					queueFamilyIndexCount
1083 			DE_NULL,												// const uint32_t*			pQueueFamilyIndices
1084 			VK_IMAGE_LAYOUT_UNDEFINED								// VkImageLayout			initialLayout
1085 		};
1086 
1087 		outputImage = createImage(vk, device, &outputImageCreateInfo, DE_NULL);
1088 		outputImageAllocation = allocator.allocate(getImageMemoryRequirements(vk, device, *outputImage), MemoryRequirement::Any);
1089 		vk.bindImageMemory(device, *outputImage, outputImageAllocation->getMemory(), outputImageAllocation->getOffset());
1090 
1091 		VkImageSubresourceRange imageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1092 		const VkImageViewCreateInfo outputImageViewCreateInfo =
1093 		{
1094 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,				// VkStructureType			sType
1095 			DE_NULL,												// const void*				pNext
1096 			(VkImageViewCreateFlags)0,								// VkImageViewCreateFlags	flags
1097 			*outputImage,											// VkImage					image
1098 			VK_IMAGE_VIEW_TYPE_2D,									// VkImageViewType			viewType
1099 			VK_FORMAT_R32G32B32A32_SFLOAT,							// VkFormat					format,
1100 			makeComponentMappingRGBA(),								// VkComponentMapping		components
1101 			imageSubresourceRange									// VkImageSubresourceRange	imageSubresourceRange
1102 		};
1103 
1104 		outputImageView = createImageView(vk, device, &outputImageViewCreateInfo);
1105 	}
1106 
1107 	// Validation buffer
1108 	{
1109 		VkDeviceSize  pixelSize = getPixelSize(mapVkFormat(VK_FORMAT_R32G32B32A32_SFLOAT));
1110 		const VkBufferCreateInfo sampleLocationBufferCreateInfo =
1111 		{
1112 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,				// VkStructureType		sType
1113 			DE_NULL,											// const void*			pNext
1114 			(VkBufferCreateFlags)0,								// VkBufferCreateFlags	flags
1115 			m_sampleCount * m_renderSize.x() * m_renderSize.y() * pixelSize,	// VkDeviceSize			size
1116 			VK_BUFFER_USAGE_TRANSFER_DST_BIT,					// VkBufferUsageFlags	usage
1117 			VK_SHARING_MODE_EXCLUSIVE,							// VkSharingMode		mode
1118 			0u,													// uint32_t				queueFamilyIndexCount
1119 			DE_NULL												// const uint32_t*		pQueueFamilyIndices
1120 		};
1121 
1122 		sampleLocationBuffer = createBuffer(vk, device, &sampleLocationBufferCreateInfo, DE_NULL);
1123 		sampleLocationBufferAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *sampleLocationBuffer), MemoryRequirement::HostVisible);
1124 		vk.bindBufferMemory(device, *sampleLocationBuffer, sampleLocationBufferAllocation->getMemory(), sampleLocationBufferAllocation->getOffset());
1125 	}
1126 
1127 	// Descriptors
1128 	{
1129 		DescriptorSetLayoutBuilder		layoutBuilder;
1130 		layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT);
1131 		descriptorSetLayout = layoutBuilder.build(vk, device);
1132 		descriptorPool = DescriptorPoolBuilder()
1133 			.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1134 			.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1135 
1136 		const VkDescriptorSetAllocateInfo descriptorSetAllocInfo =
1137 		{
1138 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1139 			DE_NULL,
1140 			*descriptorPool,
1141 			1u,
1142 			&*descriptorSetLayout
1143 		};
1144 
1145 		descriptorSet = allocateDescriptorSet(vk, device, &descriptorSetAllocInfo);
1146 
1147 		const VkDescriptorImageInfo imageInfo =
1148 		{
1149 			(VkSampler)DE_NULL,
1150 			*outputImageView,
1151 			VK_IMAGE_LAYOUT_GENERAL
1152 		};
1153 
1154 		DescriptorSetUpdateBuilder()
1155 			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageInfo)
1156 			.update(vk, device);
1157 	}
1158 
1159 	// Command Pool
1160 	{
1161 		const VkCommandPoolCreateInfo cmdPoolCreateInfo =
1162 		{
1163 			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,			// VkStructureType			sType
1164 			DE_NULL,											// const void*				pNext
1165 			VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,	// VkCommandPoolCreateFlags	flags
1166 			queueFamilyIndex									// uint32_t					queueFamilyIndex
1167 		};
1168 
1169 		cmdPool = createCommandPool(vk, device, &cmdPoolCreateInfo);
1170 	}
1171 
1172 	// Command buffer for data transfers
1173 	{
1174 		const VkCommandBufferAllocateInfo cmdBufferAllocInfo =
1175 		{
1176 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType		sType,
1177 			DE_NULL,										// const void*			pNext
1178 			*cmdPool,										// VkCommandPool		commandPool
1179 			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel	level
1180 			1u												// uint32_t				bufferCount
1181 		};
1182 
1183 		transferCmdBuffer = allocateCommandBuffer(vk, device, &cmdBufferAllocInfo);
1184 	}
1185 
1186 	// Transition the output image to LAYOUT_GENERAL
1187 	{
1188 		const VkImageMemoryBarrier barrier =
1189 		{
1190 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType		sType
1191 			DE_NULL,									// const void*			pNext
1192 			0u,											// VkAccessFlags		srcAccessMask
1193 			VK_ACCESS_SHADER_WRITE_BIT,					// VkAccessFlags		dstAccessMask
1194 			VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout		oldLayout
1195 			VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout		newLayout
1196 			VK_QUEUE_FAMILY_IGNORED,					// uint32_t				srcQueueFamilyIndex
1197 			VK_QUEUE_FAMILY_IGNORED,					// uint32_t				dstQueueFamilyIndex
1198 			*outputImage,								// VkImage				image
1199 			{
1200 				VK_IMAGE_ASPECT_COLOR_BIT,			// VkImageAspectFlags	aspectMask
1201 				0u,									// uint32_t				baseMipLevel
1202 				1u,									// uint32_t				mipLevels
1203 				0u,									// uint32_t				baseArray
1204 				1u									// uint32_t				arraySize
1205 			}
1206 		};
1207 
1208 		beginCommandBuffer(vk, *transferCmdBuffer);
1209 		vk.cmdPipelineBarrier(*transferCmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
1210 				(VkDependencyFlags)0,
1211 				0, (const VkMemoryBarrier*)DE_NULL,
1212 				0, (const VkBufferMemoryBarrier*)DE_NULL,
1213 				1, &barrier);
1214 
1215 		endCommandBuffer(vk, *transferCmdBuffer);
1216 
1217 		submitCommandsAndWait(vk, device, queue, transferCmdBuffer.get());
1218 	}
1219 
1220 	// Perform draw
1221 	{
1222 		std::vector<Vec4>				vertices;
1223 		std::vector<VulkanShader>		shaders;
1224 
1225 		vertices.push_back(Vec4( -1.0f,	-1.0f,	0.0f,	1.0f));
1226 		vertices.push_back(Vec4( -1.0f,	 1.0f,	0.0f,	1.0f));
1227 		vertices.push_back(Vec4(  1.0f,	-1.0f,	0.0f,	1.0f));
1228 		vertices.push_back(Vec4(  1.0f,	 1.0f,	0.0f,	1.0f));
1229 
1230 		shaders.push_back(VulkanShader(VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("FragCoordMsaaVert")));
1231 		shaders.push_back(VulkanShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("FragCoordMsaaFrag")));
1232 
1233 		DrawState			drawState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, m_renderSize.x(), m_renderSize.y());
1234 		DrawCallData		drawCallData(vertices);
1235 		VulkanProgram		vulkanProgram(shaders);
1236 
1237 		drawState.numSamples				= m_sampleCount;
1238 		drawState.sampleShadingEnable		= true;
1239 		vulkanProgram.descriptorSetLayout	= *descriptorSetLayout;
1240 		vulkanProgram.descriptorSet			= *descriptorSet;
1241 
1242 		VulkanDrawContext	vulkanDrawContext(m_context, drawState, drawCallData, vulkanProgram);
1243 		vulkanDrawContext.draw();
1244 
1245 		log << TestLog::Image(	"result",
1246 								"result",
1247 								tcu::ConstPixelBufferAccess(tcu::TextureFormat(
1248 										vulkanDrawContext.getColorPixels().getFormat()),
1249 										vulkanDrawContext.getColorPixels().getWidth(),
1250 										vulkanDrawContext.getColorPixels().getHeight(),
1251 										1,
1252 										vulkanDrawContext.getColorPixels().getDataPtr()));
1253 	}
1254 
1255 	// Transfer location image to buffer
1256 	{
1257 		beginCommandBuffer(vk, *transferCmdBuffer);
1258 		copyImageToBuffer(vk, *transferCmdBuffer, *outputImage, *sampleLocationBuffer, tcu::IVec2(m_renderSize.x() * m_sampleCount, m_renderSize.y()), VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
1259 		endCommandBuffer(vk, *transferCmdBuffer);
1260 
1261 		submitCommandsAndWait(vk, device, queue, transferCmdBuffer.get());
1262 
1263 		invalidateAlloc(vk, device, *sampleLocationBufferAllocation);
1264 	}
1265 
1266 	// Validate result
1267 	{
1268 		bool status;
1269 
1270 		ConstPixelBufferAccess sampleLocationPixelBuffer(mapVkFormat(VK_FORMAT_R32G32B32A32_SFLOAT), m_sampleCount * m_renderSize.x(),
1271 				m_renderSize.y(), 1u, sampleLocationBufferAllocation->getHostPtr());
1272 
1273 		status = validateSampleLocations(sampleLocationPixelBuffer);
1274 		if (status)
1275 			return TestStatus::pass("FragCoordMsaa passed");
1276 		else
1277 			return TestStatus::fail("FragCoordMsaa failed");
1278 	}
1279 }
1280 
pixelOffsetCompare(const Vec2 & a,const Vec2 & b)1281 static bool pixelOffsetCompare (const Vec2& a, const Vec2& b)
1282 {
1283 	return a.x() < b.x();
1284 }
1285 
validateSampleLocations(const ConstPixelBufferAccess & sampleLocationBuffer) const1286 bool BuiltinFragCoordMsaaCaseInstance::validateSampleLocations (const ConstPixelBufferAccess& sampleLocationBuffer) const
1287 {
1288 	const InstanceInterface&	vki					= m_context.getInstanceInterface();
1289 	TestLog&					log					= m_context.getTestContext().getLog();
1290 	const VkPhysicalDevice		physicalDevice		= m_context.getPhysicalDevice();
1291 	deUint32					logSampleCount		= deLog2Floor32(m_sampleCount);
1292 	VkPhysicalDeviceProperties	physicalDeviceProperties;
1293 
1294 	static const Vec2 sampleCount1Bit[] =
1295 	{
1296 		Vec2(0.5f, 0.5f)
1297 	};
1298 
1299 	static const Vec2 sampleCount2Bit[] =
1300 	{
1301 		Vec2(0.25f, 0.25f), Vec2(0.75f, 0.75f)
1302 	};
1303 
1304 	static const Vec2 sampleCount4Bit[] =
1305 	{
1306 		Vec2(0.375f, 0.125f), Vec2(0.875f, 0.375f), Vec2(0.125f, 0.625f), Vec2(0.625f, 0.875f)
1307 	};
1308 
1309 	static const Vec2 sampleCount8Bit[] =
1310 	{
1311 		Vec2(0.5625f, 0.3125f), Vec2(0.4375f, 0.6875f), Vec2(0.8125f,0.5625f), Vec2(0.3125f, 0.1875f),
1312 		Vec2(0.1875f, 0.8125f), Vec2(0.0625f, 0.4375f), Vec2(0.6875f,0.9375f), Vec2(0.9375f, 0.0625f)
1313 	};
1314 
1315 	static const Vec2 sampleCount16Bit[] =
1316 	{
1317 		Vec2(0.5625f, 0.5625f), Vec2(0.4375f, 0.3125f), Vec2(0.3125f,0.6250f), Vec2(0.7500f, 0.4375f),
1318 		Vec2(0.1875f, 0.3750f), Vec2(0.6250f, 0.8125f), Vec2(0.8125f,0.6875f), Vec2(0.6875f, 0.1875f),
1319 		Vec2(0.3750f, 0.8750f), Vec2(0.5000f, 0.0625f), Vec2(0.2500f,0.1250f), Vec2(0.1250f, 0.7500f),
1320 		Vec2(0.0000f, 0.5000f), Vec2(0.9375f, 0.2500f), Vec2(0.8750f,0.9375f), Vec2(0.0625f, 0.0000f)
1321 	};
1322 
1323 	static const Vec2* standardSampleLocationTable[] =
1324 	{
1325 		sampleCount1Bit,
1326 		sampleCount2Bit,
1327 		sampleCount4Bit,
1328 		sampleCount8Bit,
1329 		sampleCount16Bit
1330 	};
1331 
1332 	vki.getPhysicalDeviceProperties(physicalDevice, &physicalDeviceProperties);
1333 
1334 	for (deInt32 rowNdx = 0; rowNdx < (deInt32)m_renderSize.y(); rowNdx++)
1335 	{
1336 		for (deInt32 colNdx = 0; colNdx < (deInt32)m_renderSize.x(); colNdx++)
1337 		{
1338 			std::vector<Vec2> locations;
1339 
1340 			for (deUint32 sampleNdx = 0; sampleNdx < (deUint32)m_sampleCount; sampleNdx++)
1341 			{
1342 				const UVec2 pixelAddress	= UVec2(sampleNdx + m_sampleCount * colNdx, rowNdx);
1343 				const Vec4  pixelData		= sampleLocationBuffer.getPixel(pixelAddress.x(), pixelAddress.y());
1344 
1345 				locations.push_back(Vec2(pixelData.x(), pixelData.y()));
1346 			}
1347 
1348 			std::sort(locations.begin(), locations.end(), pixelOffsetCompare);
1349 			for (std::vector<Vec2>::const_iterator sampleIt = locations.begin(); sampleIt != locations.end(); sampleIt++)
1350 			{
1351 				IVec2	sampleFloor(deFloorFloatToInt32((*sampleIt).x()), deFloorFloatToInt32((*sampleIt).y()));
1352 				IVec2	sampleCeil(deCeilFloatToInt32((*sampleIt).x()), deCeilFloatToInt32((*sampleIt).y()));
1353 
1354 				if ( (sampleFloor.x() < colNdx) || (sampleCeil.x() > colNdx + 1) || (sampleFloor.y() < rowNdx) || (sampleCeil.y() > rowNdx + 1) )
1355 				{
1356 					log << TestLog::Message << "Pixel (" << colNdx << "," << rowNdx << "): " << *sampleIt << TestLog::EndMessage;
1357 					return false;
1358 				}
1359 			}
1360 
1361 			std::vector<Vec2>::iterator last = std::unique(locations.begin(), locations.end());
1362 			if (last != locations.end())
1363 			{
1364 				log << TestLog::Message << "Fail: Sample locations contains non-unique entry" << TestLog::EndMessage;
1365 				return false;
1366 			}
1367 
1368 			// Check standard sample locations
1369 			if (logSampleCount < DE_LENGTH_OF_ARRAY(standardSampleLocationTable))
1370 			{
1371 				if (physicalDeviceProperties.limits.standardSampleLocations)
1372 				{
1373 					for (deUint32 sampleNdx = 0; sampleNdx < (deUint32)m_sampleCount; sampleNdx++)
1374 					{
1375 						if (!de::contains(locations.begin(), locations.end(), standardSampleLocationTable[logSampleCount][sampleNdx] + Vec2(float(colNdx), float(rowNdx))))
1376 						{
1377 							log << TestLog::Message << "Didn't match sample locations " << standardSampleLocationTable[logSampleCount][sampleNdx] << TestLog::EndMessage;
1378 							return false;
1379 						}
1380 					}
1381 				}
1382 			}
1383 		}
1384 	}
1385 
1386 	return true;
1387 }
1388 
1389 class BuiltinFragCoordMsaaTestCase : public TestCase
1390 {
1391 public:
1392 					BuiltinFragCoordMsaaTestCase	(TestContext& testCtx, const char* name, const char* description, VkSampleCountFlagBits sampleCount);
1393 	virtual			~BuiltinFragCoordMsaaTestCase	(void);
1394 	void			initPrograms					(SourceCollections& sourceCollections) const;
1395 	TestInstance*	createInstance					(Context& context) const;
1396 private:
1397 	const VkSampleCountFlagBits			m_sampleCount;
1398 };
1399 
BuiltinFragCoordMsaaTestCase(TestContext & testCtx,const char * name,const char * description,VkSampleCountFlagBits sampleCount)1400 BuiltinFragCoordMsaaTestCase::BuiltinFragCoordMsaaTestCase (TestContext& testCtx, const char* name, const char* description, VkSampleCountFlagBits sampleCount)
1401 	: TestCase			(testCtx, name, description)
1402 	, m_sampleCount		(sampleCount)
1403 {
1404 }
1405 
~BuiltinFragCoordMsaaTestCase(void)1406 BuiltinFragCoordMsaaTestCase::~BuiltinFragCoordMsaaTestCase (void)
1407 {
1408 }
1409 
initPrograms(SourceCollections & programCollection) const1410 void BuiltinFragCoordMsaaTestCase::initPrograms (SourceCollections& programCollection) const
1411 {
1412 	{
1413 		std::ostringstream vertexSource;
1414 		vertexSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1415 			<< "\n"
1416 			<<  "layout (location = 0) in vec4 position;\n"
1417 			<< "void main()\n"
1418 			<< "{\n"
1419 			<< "	gl_Position = position;\n"
1420 			<< "}\n";
1421 		programCollection.glslSources.add("FragCoordMsaaVert") << glu::VertexSource(vertexSource.str());
1422 	}
1423 
1424 	{
1425 		std::ostringstream fragmentSource;
1426 		fragmentSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1427 			<< "\n"
1428 			<< "layout(location = 0) out mediump vec4 color;\n"
1429 			<< "layout (set = 0, binding = 0, rgba32f) writeonly uniform image2D storageImage;\n"
1430 			<< "void main()\n"
1431 			<< "{\n"
1432 			<< "	const int sampleNdx = int(gl_SampleID);\n"
1433 			<< "	ivec2 imageCoord = ivec2(sampleNdx + int(gl_FragCoord.x) * " << m_sampleCount << ", int(gl_FragCoord.y));\n"
1434 			<< "	imageStore(storageImage, imageCoord, vec4(gl_FragCoord.xy,vec2(0)));\n"
1435 			<< "	color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1436 			<< "}\n";
1437 		programCollection.glslSources.add("FragCoordMsaaFrag") << glu::FragmentSource(fragmentSource.str());
1438 	}
1439 }
1440 
createInstance(Context & context) const1441 TestInstance* BuiltinFragCoordMsaaTestCase::createInstance (Context& context) const
1442 {
1443 	return new BuiltinFragCoordMsaaCaseInstance(context, m_sampleCount);
1444 }
1445 
1446 class BuiltinFragDepthCase : public TestCase
1447 {
1448 public:
1449 					BuiltinFragDepthCase		(TestContext& testCtx, const char* name, const char* description, VkPrimitiveTopology topology,  VkFormat format, bool largeDepthEnable, bool depthClampEnable, const VkSampleCountFlagBits samples);
1450 	virtual			~BuiltinFragDepthCase		(void);
1451 
1452 	void			initPrograms				(SourceCollections& dst) const;
1453 	TestInstance*	createInstance				(Context& context) const;
1454 
1455 private:
1456 	const VkPrimitiveTopology		m_topology;
1457 	const VkFormat					m_format;
1458 	const bool						m_largeDepthEnable;
1459 	const float						m_defaultDepth;
1460 	const bool						m_depthClampEnable;
1461 	const VkSampleCountFlagBits		m_samples;
1462 };
1463 
BuiltinFragDepthCase(TestContext & testCtx,const char * name,const char * description,VkPrimitiveTopology topology,VkFormat format,bool largeDepthEnable,bool depthClampEnable,const VkSampleCountFlagBits samples)1464 BuiltinFragDepthCase::BuiltinFragDepthCase (TestContext& testCtx, const char* name, const char* description, VkPrimitiveTopology topology, VkFormat format, bool largeDepthEnable, bool depthClampEnable, const VkSampleCountFlagBits  samples)
1465 	: TestCase				(testCtx, name, description)
1466 	, m_topology			(topology)
1467 	, m_format				(format)
1468 	, m_largeDepthEnable	(largeDepthEnable)
1469 	, m_defaultDepth		(0.0f)
1470 	, m_depthClampEnable	(depthClampEnable)
1471 	, m_samples				(samples)
1472 {
1473 }
1474 
~BuiltinFragDepthCase(void)1475 BuiltinFragDepthCase::~BuiltinFragDepthCase(void)
1476 {
1477 }
1478 
initPrograms(SourceCollections & programCollection) const1479 void BuiltinFragDepthCase::initPrograms (SourceCollections& programCollection) const
1480 {
1481 	// Vertex
1482 	{
1483 		// Pass 1
1484 		{
1485 			std::ostringstream vertexSource;
1486 			vertexSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1487 				<< "\n"
1488 				<<  "layout (location = 0) in vec4 position;\n"
1489 				<< "void main()\n"
1490 				<< "{\n"
1491 				<< "	gl_Position = position;\n"
1492 				<< "	gl_PointSize = 1.0;\n"
1493 				<< "}\n";
1494 			programCollection.glslSources.add("FragDepthVert") << glu::VertexSource(vertexSource.str());
1495 		}
1496 
1497 		// Pass 2
1498 		{
1499 			std::ostringstream vertexSource;
1500 			vertexSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1501 				<< "\n"
1502 				<<  "layout (location = 0) in vec4 position;\n"
1503 				<<  "layout (location = 1) out vec2 texCoord;\n"
1504 				<< "void main()\n"
1505 				<< "{\n"
1506 				<< "	gl_Position = position;\n"
1507 				<< "	gl_PointSize = 1.0;\n"
1508 				<< "	texCoord = position.xy/2 + vec2(0.5);\n"
1509 				<< "}\n";
1510 			programCollection.glslSources.add("FragDepthVertPass2") << glu::VertexSource(vertexSource.str());
1511 		}
1512 	}
1513 
1514 	// Fragment
1515 	{
1516 		// Pass 1
1517 		{
1518 			std::ostringstream	fragmentSource;
1519 			fragmentSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1520 				<< "\n"
1521 				<< "layout(location = 0) out mediump vec4 color;\n"
1522 				<< "layout (std140, set = 0, binding = 0) uniform control_buffer_t\n"
1523 				<< "{\n"
1524 				<< "	float data[256];\n"
1525 				<< "} control_buffer;\n"
1526 				<< "layout (set = 0, binding = 1, rgba8ui) writeonly uniform uimage2D storageImage;\n"
1527 				<< "float controlDepthValue;\n"
1528 				<< "void recheck(float controlDepthValue)\n"
1529 				<< "{\n"
1530 				<< "	if (gl_FragDepth != controlDepthValue)\n"
1531 				<< "		gl_FragDepth = 1.0;\n"
1532 				<< "}\n"
1533 				<< "void main()\n"
1534 				<< "{\n"
1535 				<< "	const int numSamples = " << m_samples << ";\n"
1536 				<< "	if (int(gl_FragCoord.x) == " << BuiltinFragDepthCaseInstance::RENDERWIDTH/4 << ")\n"
1537 				<< "		discard;\n"
1538 				<< "	highp int index =int(gl_FragCoord.y) * " << BuiltinFragDepthCaseInstance::RENDERHEIGHT << " + int(gl_FragCoord.x);\n"
1539 				<< "	controlDepthValue = control_buffer.data[index];\n"
1540 				<< "	gl_FragDepth = controlDepthValue;\n"
1541 				<< "	const int sampleNdx = int(gl_SampleID);\n"
1542 				<< "	ivec2 imageCoord = ivec2(sampleNdx + int(gl_FragCoord.x) * " << m_samples << ", int(gl_FragCoord.y));\n"
1543 				<< "	imageStore(storageImage, imageCoord, uvec4(1));\n"
1544 				<< "	recheck(controlDepthValue);\n"
1545 				<< "	color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1546 				<< "}\n";
1547 			programCollection.glslSources.add("FragDepthFrag") << glu::FragmentSource(fragmentSource.str());
1548 		}
1549 
1550 		// Pass 2
1551 		{
1552 			const char* multisampleDecoration = m_samples != VK_SAMPLE_COUNT_1_BIT ? "MS" : "";
1553 			std::ostringstream fragmentSource;
1554 			fragmentSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1555 				<< "\n"
1556 				<< "layout (location = 0) out mediump vec4 color;\n"
1557 				<< "layout (location = 1) in vec2 texCoord;\n"
1558 				<< "layout (binding = 0, set = 0) uniform sampler2D" << multisampleDecoration << " u_depthTex;\n"
1559 				<< "layout (binding = 1, set = 0, r32f) writeonly uniform image2D u_outImage;\n"
1560 				<< "void main (void)\n"
1561 				<< "{\n"
1562 				<< "	const int numSamples = " << m_samples << ";\n"
1563 				<< "	const int sampleNdx = int(gl_SampleID);\n"
1564 				<< "	ivec2 renderSize = ivec2(" << BuiltinFragDepthCaseInstance::RENDERWIDTH << "," << BuiltinFragDepthCaseInstance::RENDERHEIGHT << ");\n"
1565 				<< "	ivec2 imageCoord = ivec2(int(texCoord.x * renderSize.x), int(texCoord.y * renderSize.y));\n"
1566 				<< "	vec4 depthVal = texelFetch(u_depthTex, imageCoord, sampleNdx);\n"
1567 				<< "	imageStore(u_outImage, ivec2(sampleNdx + int(texCoord.x * renderSize.x) * numSamples, int(texCoord.y * renderSize.y)), depthVal);\n"
1568 				<< "	color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1569 				<< "}\n";
1570 			programCollection.glslSources.add("FragDepthFragPass2") << glu::FragmentSource(fragmentSource.str());
1571 		}
1572 	}
1573 }
1574 
createInstance(Context & context) const1575 TestInstance* BuiltinFragDepthCase::createInstance (Context& context) const
1576 {
1577 	return new BuiltinFragDepthCaseInstance(context, m_topology, m_format, m_largeDepthEnable, m_defaultDepth, m_depthClampEnable, m_samples);
1578 }
1579 
1580 class BuiltinGlFragCoordXYZCaseInstance : public ShaderRenderCaseInstance
1581 {
1582 public:
1583 					BuiltinGlFragCoordXYZCaseInstance	(Context& context);
1584 
1585 	TestStatus		iterate								(void);
1586 	virtual void	setupDefaultInputs					(void);
1587 };
1588 
BuiltinGlFragCoordXYZCaseInstance(Context & context)1589 BuiltinGlFragCoordXYZCaseInstance::BuiltinGlFragCoordXYZCaseInstance (Context& context)
1590 	: ShaderRenderCaseInstance	(context)
1591 {
1592 	m_colorFormat = VK_FORMAT_R16G16B16A16_UNORM;
1593 }
1594 
iterate(void)1595 TestStatus BuiltinGlFragCoordXYZCaseInstance::iterate (void)
1596 {
1597 	const UVec2		viewportSize	= getViewportSize();
1598 	const int		width			= viewportSize.x();
1599 	const int		height			= viewportSize.y();
1600 	const tcu::Vec3	scale			(1.f / float(width), 1.f / float(height), 1.0f);
1601 	const float		precision		= 0.00001f;
1602 	const deUint16	indices[6]		=
1603 	{
1604 		2, 1, 3,
1605 		0, 1, 2,
1606 	};
1607 
1608 	setup();
1609 	addUniform(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, scale);
1610 
1611 	render(4, 2, indices);
1612 
1613 	// Reference image
1614 	for (int y = 0; y < height; y++)
1615 	{
1616 		for (int x = 0; x < width; x++)
1617 		{
1618 			const float	xf			= (float(x) + .5f) / float(width);
1619 			const float	yf			= (float(height - y - 1) + .5f) / float(height);
1620 			const float	z			= (xf + yf) / 2.0f;
1621 			const Vec3	fragCoord	(float(x) + .5f, float(y) + .5f, z);
1622 			const Vec3	scaledFC	= fragCoord*scale;
1623 			const Vec4	color		(scaledFC.x(), scaledFC.y(), scaledFC.z(), 1.0f);
1624 			const Vec4	resultColor	= getResultImage().getAccess().getPixel(x, y);
1625 
1626 			if (de::abs(color.x() - resultColor.x()) > precision ||
1627 				de::abs(color.y() - resultColor.y()) > precision ||
1628 				de::abs(color.z() - resultColor.z()) > precision)
1629 			return TestStatus::fail("Image mismatch");
1630 		}
1631 	}
1632 
1633 	return TestStatus::pass("Result image matches reference");
1634 }
1635 
setupDefaultInputs(void)1636 void BuiltinGlFragCoordXYZCaseInstance::setupDefaultInputs (void)
1637 {
1638 	const float		vertices[]		=
1639 	{
1640 		-1.0f,  1.0f,  0.0f, 1.0f,
1641 		-1.0f, -1.0f,  0.5f, 1.0f,
1642 		 1.0f,  1.0f,  0.5f, 1.0f,
1643 		 1.0f, -1.0f,  1.0f, 1.0f,
1644 	};
1645 
1646 	addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float) * 4), 4, vertices);
1647 }
1648 
1649 class BuiltinGlFragCoordXYZCase : public TestCase
1650 {
1651 public:
1652 								BuiltinGlFragCoordXYZCase	(TestContext& testCtx, const string& name, const string& description);
1653 	virtual						~BuiltinGlFragCoordXYZCase	(void);
1654 
1655 	void						initPrograms				(SourceCollections& dst) const;
1656 	TestInstance*				createInstance				(Context& context) const;
1657 
1658 private:
1659 								BuiltinGlFragCoordXYZCase	(const BuiltinGlFragCoordXYZCase&);	// not allowed!
1660 	BuiltinGlFragCoordXYZCase&	operator=					(const BuiltinGlFragCoordXYZCase&);	// not allowed!
1661 };
1662 
BuiltinGlFragCoordXYZCase(TestContext & testCtx,const string & name,const string & description)1663 BuiltinGlFragCoordXYZCase::BuiltinGlFragCoordXYZCase (TestContext& testCtx, const string& name, const string& description)
1664 	: TestCase(testCtx, name, description)
1665 {
1666 }
1667 
~BuiltinGlFragCoordXYZCase(void)1668 BuiltinGlFragCoordXYZCase::~BuiltinGlFragCoordXYZCase (void)
1669 {
1670 }
1671 
initPrograms(SourceCollections & dst) const1672 void BuiltinGlFragCoordXYZCase::initPrograms (SourceCollections& dst) const
1673 {
1674 	dst.glslSources.add("vert") << glu::VertexSource(
1675 		"#version 310 es\n"
1676 		"layout(location = 0) in highp vec4 a_position;\n"
1677 		"void main (void)\n"
1678 		"{\n"
1679 		"       gl_Position = a_position;\n"
1680 		"}\n");
1681 
1682 	dst.glslSources.add("frag") << glu::FragmentSource(
1683 		"#version 310 es\n"
1684 		"layout(set=0, binding=0) uniform Scale { highp vec3 u_scale; };\n"
1685 		"layout(location = 0) out highp vec4 o_color;\n"
1686 		"void main (void)\n"
1687 		"{\n"
1688 		"       o_color = vec4(gl_FragCoord.xyz * u_scale, 1.0);\n"
1689 		"}\n");
1690 }
1691 
createInstance(Context & context) const1692 TestInstance* BuiltinGlFragCoordXYZCase::createInstance (Context& context) const
1693 {
1694 	return new BuiltinGlFragCoordXYZCaseInstance(context);
1695 }
1696 
projectedTriInterpolate(const Vec3 & s,const Vec3 & w,float nx,float ny)1697 inline float projectedTriInterpolate (const Vec3& s, const Vec3& w, float nx, float ny)
1698 {
1699 	return (s[0]*(1.0f-nx-ny)/w[0] + s[1]*ny/w[1] + s[2]*nx/w[2]) / ((1.0f-nx-ny)/w[0] + ny/w[1] + nx/w[2]);
1700 }
1701 
1702 class BuiltinGlFragCoordWCaseInstance : public ShaderRenderCaseInstance
1703 {
1704 public:
1705 					BuiltinGlFragCoordWCaseInstance	(Context& context);
1706 
1707 	TestStatus		iterate							(void);
1708 	virtual void	setupDefaultInputs				(void);
1709 
1710 private:
1711 
1712 	const Vec4		m_w;
1713 
1714 };
1715 
BuiltinGlFragCoordWCaseInstance(Context & context)1716 BuiltinGlFragCoordWCaseInstance::BuiltinGlFragCoordWCaseInstance (Context& context)
1717 	: ShaderRenderCaseInstance	(context)
1718 	, m_w						(1.7f, 2.0f, 1.2f, 1.0f)
1719 {
1720 	m_colorFormat = VK_FORMAT_R16G16B16A16_UNORM;
1721 }
1722 
iterate(void)1723 TestStatus BuiltinGlFragCoordWCaseInstance::iterate (void)
1724 {
1725 	const UVec2		viewportSize	= getViewportSize();
1726 	const int		width			= viewportSize.x();
1727 	const int		height			= viewportSize.y();
1728 	const float		precision		= 0.00001f;
1729 	const deUint16	indices[6]		=
1730 	{
1731 		2, 1, 3,
1732 		0, 1, 2,
1733 	};
1734 
1735 	setup();
1736 	render(4, 2, indices);
1737 
1738 	// Reference image
1739 	for (int y = 0; y < height; y++)
1740 	{
1741 		for (int x = 0; x < width; x++)
1742 		{
1743 			const float	xf			= (float(x) + .5f) / float(width);
1744 			const float	yf			= (float(height - y - 1) +.5f) / float(height);
1745 			const float	oow			= ((xf + yf) < 1.0f)
1746 										? projectedTriInterpolate(Vec3(m_w[0], m_w[1], m_w[2]), Vec3(m_w[0], m_w[1], m_w[2]), xf, yf)
1747 										: projectedTriInterpolate(Vec3(m_w[3], m_w[2], m_w[1]), Vec3(m_w[3], m_w[2], m_w[1]), 1.0f - xf, 1.0f - yf);
1748 			const Vec4	color		(0.0f, oow - 1.0f, 0.0f, 1.0f);
1749 			const Vec4	resultColor	= getResultImage().getAccess().getPixel(x, y);
1750 
1751 			if (de::abs(color.x() - resultColor.x()) > precision ||
1752 				de::abs(color.y() - resultColor.y()) > precision ||
1753 				de::abs(color.z() - resultColor.z()) > precision)
1754 			return TestStatus::fail("Image mismatch");
1755 		}
1756 	}
1757 
1758 	return TestStatus::pass("Result image matches reference");
1759 }
1760 
setupDefaultInputs(void)1761 void BuiltinGlFragCoordWCaseInstance::setupDefaultInputs (void)
1762 {
1763 	const float vertices[] =
1764 	{
1765 		-m_w[0],  m_w[0], 0.0f, m_w[0],
1766 		-m_w[1], -m_w[1], 0.0f, m_w[1],
1767 		 m_w[2],  m_w[2], 0.0f, m_w[2],
1768 		 m_w[3], -m_w[3], 0.0f, m_w[3]
1769 	};
1770 
1771 	addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float) * 4), 4, vertices);
1772 }
1773 
1774 class BuiltinGlFragCoordWCase : public TestCase
1775 {
1776 public:
1777 								BuiltinGlFragCoordWCase		(TestContext& testCtx, const string& name, const string& description);
1778 	virtual						~BuiltinGlFragCoordWCase	(void);
1779 
1780 	void						initPrograms				(SourceCollections& dst) const;
1781 	TestInstance*				createInstance				(Context& context) const;
1782 
1783 private:
1784 								BuiltinGlFragCoordWCase		(const BuiltinGlFragCoordWCase&);	// not allowed!
1785 	BuiltinGlFragCoordWCase&	operator=					(const BuiltinGlFragCoordWCase&);	// not allowed!
1786 };
1787 
BuiltinGlFragCoordWCase(TestContext & testCtx,const string & name,const string & description)1788 BuiltinGlFragCoordWCase::BuiltinGlFragCoordWCase (TestContext& testCtx, const string& name, const string& description)
1789 	: TestCase(testCtx, name, description)
1790 {
1791 }
1792 
~BuiltinGlFragCoordWCase(void)1793 BuiltinGlFragCoordWCase::~BuiltinGlFragCoordWCase (void)
1794 {
1795 }
1796 
initPrograms(SourceCollections & dst) const1797 void BuiltinGlFragCoordWCase::initPrograms (SourceCollections& dst) const
1798 {
1799 	dst.glslSources.add("vert") << glu::VertexSource(
1800 		"#version 310 es\n"
1801 		"layout(location = 0) in highp vec4 a_position;\n"
1802 		"void main (void)\n"
1803 		"{\n"
1804 		"       gl_Position = a_position;\n"
1805 		"}\n");
1806 
1807 	dst.glslSources.add("frag") << glu::FragmentSource(
1808 		"#version 310 es\n"
1809 		"layout(location = 0) out highp vec4 o_color;\n"
1810 		"void main (void)\n"
1811 		"{\n"
1812 		"       o_color = vec4(0.0, 1.0 / gl_FragCoord.w - 1.0, 0.0, 1.0);\n"
1813 		"}\n");
1814 }
1815 
createInstance(Context & context) const1816 TestInstance* BuiltinGlFragCoordWCase::createInstance (Context& context) const
1817 {
1818 	return new BuiltinGlFragCoordWCaseInstance(context);
1819 }
1820 
1821 class BuiltinGlPointCoordCaseInstance : public ShaderRenderCaseInstance
1822 {
1823 public:
1824 					BuiltinGlPointCoordCaseInstance	(Context& context);
1825 
1826 	TestStatus		iterate								(void);
1827 	virtual void	setupDefaultInputs					(void);
1828 };
1829 
BuiltinGlPointCoordCaseInstance(Context & context)1830 BuiltinGlPointCoordCaseInstance::BuiltinGlPointCoordCaseInstance (Context& context)
1831 	: ShaderRenderCaseInstance	(context)
1832 {
1833 }
1834 
iterate(void)1835 TestStatus BuiltinGlPointCoordCaseInstance::iterate (void)
1836 {
1837 	const UVec2				viewportSize	= getViewportSize();
1838 	const int				width			= viewportSize.x();
1839 	const int				height			= viewportSize.y();
1840 	const float				threshold		= 0.02f;
1841 	const int				numPoints		= 16;
1842 	vector<Vec3>			coords			(numPoints);
1843 	de::Random				rnd				(0x145fa);
1844 	Surface					resImage		(width, height);
1845 	Surface					refImage		(width, height);
1846 	bool					compareOk		= false;
1847 
1848 	// Compute coordinates.
1849 	{
1850 		const VkPhysicalDeviceLimits&	limits					= m_context.getDeviceProperties().limits;
1851 		const float						minPointSize			= limits.pointSizeRange[0];
1852 		const float						maxPointSize			= limits.pointSizeRange[1];
1853 		const int						pointSizeDeltaMultiples	= de::max(1, deCeilFloatToInt32((maxPointSize - minPointSize) / limits.pointSizeGranularity));
1854 
1855 		TCU_CHECK(minPointSize <= maxPointSize);
1856 
1857 		for (vector<Vec3>::iterator coord = coords.begin(); coord != coords.end(); ++coord)
1858 		{
1859 			coord->x() = rnd.getFloat(-0.9f, 0.9f);
1860 			coord->y() = rnd.getFloat(-0.9f, 0.9f);
1861 			coord->z() = de::min(maxPointSize, minPointSize + float(rnd.getInt(0, pointSizeDeltaMultiples)) * limits.pointSizeGranularity);
1862 		}
1863 	}
1864 
1865 	setup();
1866 	addAttribute(0u, VK_FORMAT_R32G32B32_SFLOAT, deUint32(sizeof(Vec3)), numPoints, &coords[0]);
1867 	render(numPoints, 0, DE_NULL, VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
1868 	copy(resImage.getAccess(), getResultImage().getAccess());
1869 
1870 	// Draw reference
1871 	clear(refImage.getAccess(), m_clearColor);
1872 
1873 	for (vector<Vec3>::const_iterator pointIter = coords.begin(); pointIter != coords.end(); ++pointIter)
1874 	{
1875 		const float	centerX	= float(width) *(pointIter->x()*0.5f + 0.5f);
1876 		const float	centerY	= float(height)*(pointIter->y()*0.5f + 0.5f);
1877 		const float	size	= pointIter->z();
1878 		const int	x0		= deRoundFloatToInt32(centerX - size*0.5f);
1879 		const int	y0		= deRoundFloatToInt32(centerY - size*0.5f);
1880 		const int	x1		= deRoundFloatToInt32(centerX + size*0.5f);
1881 		const int	y1		= deRoundFloatToInt32(centerY + size*0.5f);
1882 		const int	w		= x1-x0;
1883 		const int	h		= y1-y0;
1884 
1885 		for (int yo = 0; yo < h; yo++)
1886 		{
1887 			for (int xo = 0; xo < w; xo++)
1888 			{
1889 				const int		dx		= x0+xo;
1890 				const int		dy		= y0+yo;
1891 				const float		fragX	= float(dx) + 0.5f;
1892 				const float		fragY	= float(dy) + 0.5f;
1893 				const float		s		= 0.5f + (fragX - centerX) / size;
1894 				const float		t		= 0.5f + (fragY - centerY) / size;
1895 				const Vec4		color	(s, t, 0.0f, 1.0f);
1896 
1897 				if (de::inBounds(dx, 0, refImage.getWidth()) && de::inBounds(dy, 0, refImage.getHeight()))
1898 					refImage.setPixel(dx, dy, RGBA(color));
1899 			}
1900 		}
1901 	}
1902 
1903 	compareOk = fuzzyCompare(m_context.getTestContext().getLog(), "Result", "Image comparison result", refImage, resImage, threshold, COMPARE_LOG_RESULT);
1904 
1905 	if (compareOk)
1906 		return TestStatus::pass("Result image matches reference");
1907 	else
1908 		return TestStatus::fail("Image mismatch");
1909 }
1910 
setupDefaultInputs(void)1911 void BuiltinGlPointCoordCaseInstance::setupDefaultInputs (void)
1912 {
1913 }
1914 
1915 class BuiltinGlPointCoordCase : public TestCase
1916 {
1917 public:
1918 								BuiltinGlPointCoordCase	(TestContext& testCtx, const string& name, const string& description);
1919 	virtual						~BuiltinGlPointCoordCase	(void);
1920 
1921 	void						initPrograms				(SourceCollections& dst) const;
1922 	TestInstance*				createInstance				(Context& context) const;
1923 
1924 private:
1925 								BuiltinGlPointCoordCase	(const BuiltinGlPointCoordCase&);	// not allowed!
1926 	BuiltinGlPointCoordCase&	operator=					(const BuiltinGlPointCoordCase&);	// not allowed!
1927 };
1928 
BuiltinGlPointCoordCase(TestContext & testCtx,const string & name,const string & description)1929 BuiltinGlPointCoordCase::BuiltinGlPointCoordCase (TestContext& testCtx, const string& name, const string& description)
1930 	: TestCase(testCtx, name, description)
1931 {
1932 }
1933 
~BuiltinGlPointCoordCase(void)1934 BuiltinGlPointCoordCase::~BuiltinGlPointCoordCase (void)
1935 {
1936 }
1937 
initPrograms(SourceCollections & dst) const1938 void BuiltinGlPointCoordCase::initPrograms (SourceCollections& dst) const
1939 {
1940 	dst.glslSources.add("vert") << glu::VertexSource(
1941 		"#version 310 es\n"
1942 		"layout(location = 0) in highp vec3 a_position;\n"
1943 		"void main (void)\n"
1944 		"{\n"
1945 		"    gl_Position = vec4(a_position.xy, 0.0, 1.0);\n"
1946 		"    gl_PointSize = a_position.z;\n"
1947 		"}\n");
1948 
1949 	dst.glslSources.add("frag") << glu::FragmentSource(
1950 		"#version 310 es\n"
1951 		"layout(location = 0) out lowp vec4 o_color;\n"
1952 		"void main (void)\n"
1953 		"{\n"
1954 		"    o_color = vec4(gl_PointCoord, 0.0, 1.0);\n"
1955 		"}\n");
1956 }
1957 
createInstance(Context & context) const1958 TestInstance* BuiltinGlPointCoordCase::createInstance (Context& context) const
1959 {
1960 	return new BuiltinGlPointCoordCaseInstance(context);
1961 }
1962 
1963 enum ShaderInputTypeBits
1964 {
1965 	SHADER_INPUT_BUILTIN_BIT	= 0x01,
1966 	SHADER_INPUT_VARYING_BIT	= 0x02,
1967 	SHADER_INPUT_CONSTANT_BIT	= 0x04
1968 };
1969 
1970 typedef deUint16 ShaderInputTypes;
1971 
shaderInputTypeToString(ShaderInputTypes type)1972 string shaderInputTypeToString (ShaderInputTypes type)
1973 {
1974 	string typeString = "input";
1975 
1976 	if (type == 0)
1977 		return "input_none";
1978 
1979 	if (type & SHADER_INPUT_BUILTIN_BIT)
1980 		typeString += "_builtin";
1981 
1982 	if (type & SHADER_INPUT_VARYING_BIT)
1983 		typeString += "_varying";
1984 
1985 	if (type & SHADER_INPUT_CONSTANT_BIT)
1986 		typeString += "_constant";
1987 
1988 	return typeString;
1989 }
1990 
1991 class BuiltinInputVariationsCaseInstance : public ShaderRenderCaseInstance
1992 {
1993 public:
1994 							BuiltinInputVariationsCaseInstance	(Context& context, const ShaderInputTypes shaderInputTypes);
1995 
1996 	TestStatus				iterate								(void);
1997 	virtual void			setupDefaultInputs					(void);
1998 	virtual void			updatePushConstants					(vk::VkCommandBuffer commandBuffer, vk::VkPipelineLayout pipelineLayout);
1999 
2000 private:
2001 	const ShaderInputTypes	m_shaderInputTypes;
2002 	const Vec4				m_constantColor;
2003 };
2004 
BuiltinInputVariationsCaseInstance(Context & context,const ShaderInputTypes shaderInputTypes)2005 BuiltinInputVariationsCaseInstance::BuiltinInputVariationsCaseInstance (Context& context, const ShaderInputTypes shaderInputTypes)
2006 	: ShaderRenderCaseInstance	(context)
2007 	, m_shaderInputTypes		(shaderInputTypes)
2008 	, m_constantColor			(0.1f, 0.05f, 0.2f, 0.0f)
2009 {
2010 }
2011 
iterate(void)2012 TestStatus BuiltinInputVariationsCaseInstance::iterate (void)
2013 {
2014 	const UVec2					viewportSize	= getViewportSize();
2015 	const int					width			= viewportSize.x();
2016 	const int					height			= viewportSize.y();
2017 	const tcu::RGBA				threshold		(2, 2, 2, 2);
2018 	Surface						resImage		(width, height);
2019 	Surface						refImage		(width, height);
2020 	bool						compareOk		= false;
2021 	const VkPushConstantRange	pcRanges		=
2022 	{
2023 		VK_SHADER_STAGE_FRAGMENT_BIT,	// VkShaderStageFlags	stageFlags;
2024 		0u,								// deUint32				offset;
2025 		sizeof(Vec4)					// deUint32				size;
2026 	};
2027 	const deUint16				indices[12]		=
2028 	{
2029 		0, 4, 1,
2030 		0, 5, 4,
2031 		1, 2, 3,
2032 		1, 3, 4
2033 	};
2034 
2035 	setup();
2036 
2037 	if (m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT)
2038 		setPushConstantRanges(1, &pcRanges);
2039 
2040 	render(6, 4, indices);
2041 	copy(resImage.getAccess(), getResultImage().getAccess());
2042 
2043 	// Reference image
2044 	for (int y = 0; y < refImage.getHeight(); y++)
2045 	{
2046 		for (int x = 0; x < refImage.getWidth(); x++)
2047 		{
2048 			Vec4 color (0.1f, 0.2f, 0.3f, 1.0f);
2049 
2050 			if (((m_shaderInputTypes & SHADER_INPUT_BUILTIN_BIT) && (x < refImage.getWidth() / 2)) ||
2051 				!(m_shaderInputTypes & SHADER_INPUT_BUILTIN_BIT))
2052 			{
2053 				if (m_shaderInputTypes & SHADER_INPUT_VARYING_BIT)
2054 				{
2055 					const float xf = (float(x)+.5f) / float(refImage.getWidth());
2056 					color += Vec4(0.6f * (1 - xf), 0.6f * xf, 0.0f, 0.0f);
2057 				}
2058 				else
2059 					color += Vec4(0.3f, 0.2f, 0.1f, 0.0f);
2060 			}
2061 
2062 			if (m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT)
2063 				color += m_constantColor;
2064 
2065 			refImage.setPixel(x, y, RGBA(color));
2066 		}
2067 	}
2068 
2069 	compareOk = pixelThresholdCompare(m_context.getTestContext().getLog(), "Result", "Image comparison result", refImage, resImage, threshold, COMPARE_LOG_RESULT);
2070 
2071 	if (compareOk)
2072 		return TestStatus::pass("Result image matches reference");
2073 	else
2074 		return TestStatus::fail("Image mismatch");
2075 }
2076 
setupDefaultInputs(void)2077 void BuiltinInputVariationsCaseInstance::setupDefaultInputs (void)
2078 {
2079 	const float vertices[] =
2080 	{
2081 		-1.0f, -1.0f, 0.0f, 1.0f,
2082 		 0.0f, -1.0f, 0.0f, 1.0f,
2083 		 1.0f, -1.0f, 0.0f, 1.0f,
2084 		 1.0f,  1.0f, 0.0f, 1.0f,
2085 		 0.0f,  1.0f, 0.0f, 1.0f,
2086 		-1.0f,  1.0f, 0.0f, 1.0f
2087 	};
2088 
2089 	addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float) * 4), 6, vertices);
2090 
2091 	if (m_shaderInputTypes & SHADER_INPUT_VARYING_BIT)
2092 	{
2093 		const float colors[] =
2094 		{
2095 			 0.6f,  0.0f, 0.0f, 1.0f,
2096 			 0.3f,  0.3f, 0.0f, 1.0f,
2097 			 0.0f,  0.6f, 0.0f, 1.0f,
2098 			 0.0f,  0.6f, 0.0f, 1.0f,
2099 			 0.3f,  0.3f, 0.0f, 1.0f,
2100 			 0.6f,  0.0f, 0.0f, 1.0f
2101 		};
2102 		addAttribute(1u, VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float) * 4), 6, colors);
2103 	}
2104 }
2105 
updatePushConstants(vk::VkCommandBuffer commandBuffer,vk::VkPipelineLayout pipelineLayout)2106 void BuiltinInputVariationsCaseInstance::updatePushConstants (vk::VkCommandBuffer commandBuffer, vk::VkPipelineLayout pipelineLayout)
2107 {
2108 	if (m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT)
2109 	{
2110 		const DeviceInterface& vk = m_context.getDeviceInterface();
2111 		vk.cmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(Vec4), &m_constantColor);
2112 	}
2113 }
2114 
2115 class BuiltinInputVariationsCase : public TestCase
2116 {
2117 public:
2118 								BuiltinInputVariationsCase	(TestContext& testCtx, const string& name, const string& description, const ShaderInputTypes shaderInputTypes);
2119 	virtual						~BuiltinInputVariationsCase	(void);
2120 
2121 	void						initPrograms				(SourceCollections& dst) const;
2122 	TestInstance*				createInstance				(Context& context) const;
2123 
2124 private:
2125 								BuiltinInputVariationsCase	(const BuiltinInputVariationsCase&);	// not allowed!
2126 	BuiltinInputVariationsCase&	operator=					(const BuiltinInputVariationsCase&);	// not allowed!
2127 	const ShaderInputTypes		m_shaderInputTypes;
2128 };
2129 
BuiltinInputVariationsCase(TestContext & testCtx,const string & name,const string & description,ShaderInputTypes shaderInputTypes)2130 BuiltinInputVariationsCase::BuiltinInputVariationsCase (TestContext& testCtx, const string& name, const string& description, ShaderInputTypes shaderInputTypes)
2131 	: TestCase				(testCtx, name, description)
2132 	, m_shaderInputTypes	(shaderInputTypes)
2133 {
2134 }
2135 
~BuiltinInputVariationsCase(void)2136 BuiltinInputVariationsCase::~BuiltinInputVariationsCase (void)
2137 {
2138 }
2139 
initPrograms(SourceCollections & dst) const2140 void BuiltinInputVariationsCase::initPrograms (SourceCollections& dst) const
2141 {
2142 	map<string, string>			vertexParams;
2143 	map<string, string>			fragmentParams;
2144 	const tcu::StringTemplate	vertexCodeTemplate		(
2145 		"#version 450\n"
2146 		"layout(location = 0) in highp vec4 a_position;\n"
2147 		"out gl_PerVertex {\n"
2148 		"	vec4 gl_Position;\n"
2149 		"};\n"
2150 		"${VARYING_DECL}"
2151 		"void main (void)\n"
2152 		"{\n"
2153 		"    gl_Position = a_position;\n"
2154 		"    ${VARYING_USAGE}"
2155 		"}\n");
2156 
2157 	const tcu::StringTemplate	fragmentCodeTemplate	(
2158 		"#version 450\n"
2159 		"${VARYING_DECL}"
2160 		"${CONSTANT_DECL}"
2161 		"layout(location = 0) out highp vec4 o_color;\n"
2162 		"void main (void)\n"
2163 		"{\n"
2164 		"    o_color = vec4(0.1, 0.2, 0.3, 1.0);\n"
2165 		"    ${BUILTIN_USAGE}"
2166 		"    ${VARYING_USAGE}"
2167 		"    ${CONSTANT_USAGE}"
2168 		"}\n");
2169 
2170 	vertexParams["VARYING_DECL"]		=
2171 		m_shaderInputTypes & SHADER_INPUT_VARYING_BIT	? "layout(location = 1) in highp vec4 a_color;\n"
2172 														  "layout(location = 0) out highp vec4 v_color;\n"
2173 														: "";
2174 
2175 	vertexParams["VARYING_USAGE"]		=
2176 		m_shaderInputTypes & SHADER_INPUT_VARYING_BIT	? "v_color = a_color;\n"
2177 														: "";
2178 
2179 	fragmentParams["VARYING_DECL"]		=
2180 		m_shaderInputTypes & SHADER_INPUT_VARYING_BIT	? "layout(location = 0) in highp vec4 a_color;\n"
2181 														: "";
2182 
2183 	fragmentParams["CONSTANT_DECL"]		=
2184 		m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT	? "layout(push_constant) uniform PCBlock {\n"
2185 														  "  vec4 color;\n"
2186 														  "} pc;\n"
2187 														: "";
2188 
2189 	fragmentParams["BUILTIN_USAGE"]		=
2190 		m_shaderInputTypes & SHADER_INPUT_BUILTIN_BIT	? "if (gl_FrontFacing)\n"
2191 														: "";
2192 
2193 	fragmentParams["VARYING_USAGE"]		=
2194 		m_shaderInputTypes & SHADER_INPUT_VARYING_BIT	? "o_color += vec4(a_color.xyz, 0.0);\n"
2195 														: "o_color += vec4(0.3, 0.2, 0.1, 0.0);\n";
2196 
2197 
2198 	fragmentParams["CONSTANT_USAGE"]	=
2199 		m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT	? "o_color += pc.color;\n"
2200 														: "";
2201 
2202 	dst.glslSources.add("vert") << glu::VertexSource(vertexCodeTemplate.specialize(vertexParams));
2203 	dst.glslSources.add("frag") << glu::FragmentSource(fragmentCodeTemplate.specialize(fragmentParams));
2204 }
2205 
createInstance(Context & context) const2206 TestInstance* BuiltinInputVariationsCase::createInstance (Context& context) const
2207 {
2208 	return new BuiltinInputVariationsCaseInstance(context, m_shaderInputTypes);
2209 }
2210 
2211 } // anonymous
2212 
createBuiltinVarTests(TestContext & testCtx)2213 TestCaseGroup* createBuiltinVarTests (TestContext& testCtx)
2214 {
2215 	de::MovePtr<TestCaseGroup> builtinGroup			(new TestCaseGroup(testCtx, "builtin_var", "Shader builtin variable tests."));
2216 	de::MovePtr<TestCaseGroup> simpleGroup			(new TestCaseGroup(testCtx, "simple", "Simple cases."));
2217 	de::MovePtr<TestCaseGroup> inputVariationsGroup	(new TestCaseGroup(testCtx, "input_variations", "Input type variation tests."));
2218 	de::MovePtr<TestCaseGroup> frontFacingGroup		(new TestCaseGroup(testCtx, "frontfacing", "Test gl_Frontfacing keyword."));
2219 	de::MovePtr<TestCaseGroup> fragDepthGroup		(new TestCaseGroup(testCtx, "fragdepth", "Test gl_FragDepth keyword."));
2220 	de::MovePtr<TestCaseGroup> fragCoordMsaaGroup	(new TestCaseGroup(testCtx, "fragcoord_msaa", "Test interation between gl_FragCoord and msaa"));
2221 
2222 	simpleGroup->addChild(new BuiltinGlFragCoordXYZCase(testCtx, "fragcoord_xyz", "FragCoord xyz test"));
2223 	simpleGroup->addChild(new BuiltinGlFragCoordWCase(testCtx, "fragcoord_w", "FragCoord w test"));
2224 	simpleGroup->addChild(new BuiltinGlPointCoordCase(testCtx, "pointcoord", "PointCoord test"));
2225 
2226 	// FragCoord_msaa
2227 	{
2228 		static const struct FragCoordMsaaCaseList
2229 		{
2230 			const char*				name;
2231 			const char*				description;
2232 			VkSampleCountFlagBits	sampleCount;
2233 		} fragCoordMsaaCaseList[] =
2234 		{
2235 			{ "1_bit",	"Test FragCoord locations with 2 samples", VK_SAMPLE_COUNT_1_BIT },
2236 			{ "2_bit",	"Test FragCoord locations with 2 samples", VK_SAMPLE_COUNT_2_BIT },
2237 			{ "4_bit",	"Test FragCoord locations with 4 samples", VK_SAMPLE_COUNT_4_BIT },
2238 			{ "8_bit",	"Test FragCoord locations with 8 samples", VK_SAMPLE_COUNT_8_BIT },
2239 			{ "16_bit",	"Test FragCoord locations with 16 samples", VK_SAMPLE_COUNT_16_BIT },
2240 			{ "32_bit", "Test FragCoord locations with 32 samples", VK_SAMPLE_COUNT_32_BIT },
2241 			{ "64-bit", "Test FragCoord locaitons with 64 samples", VK_SAMPLE_COUNT_64_BIT }
2242 		};
2243 
2244 		for (deUint32 caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(fragCoordMsaaCaseList); caseNdx++)
2245 			fragCoordMsaaGroup->addChild(new BuiltinFragCoordMsaaTestCase(testCtx, fragCoordMsaaCaseList[caseNdx].name, fragCoordMsaaCaseList[caseNdx].description, fragCoordMsaaCaseList[caseNdx].sampleCount));
2246 	}
2247 
2248 	// gl_FrontFacing tests
2249 	{
2250 		static const struct PrimitiveTable
2251 		{
2252 			const char*				name;
2253 			const char*				desc;
2254 			VkPrimitiveTopology		primitive;
2255 		} frontfacingCases[] =
2256 		{
2257 			{ "point_list",		"Test that points are frontfacing",							VK_PRIMITIVE_TOPOLOGY_POINT_LIST },
2258 			{ "line_list",		"Test that lines are frontfacing",							VK_PRIMITIVE_TOPOLOGY_LINE_LIST },
2259 			{ "triangle_list",	"Test that triangles can be frontfacing or backfacing",		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST },
2260 			{ "triangle_strip",	"Test that traiangle strips can be front or back facing",	VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP },
2261 			{ "triangle_fan",	"Test that triangle fans can be front or back facing",		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN },
2262 		};
2263 
2264 		for (deUint32 ndx = 0; ndx < DE_LENGTH_OF_ARRAY(frontfacingCases); ndx++)
2265 			frontFacingGroup->addChild(new BuiltinGlFrontFacingCase(testCtx, frontfacingCases[ndx].primitive, frontfacingCases[ndx].name, frontfacingCases[ndx].desc));
2266 	}
2267 
2268 	// gl_FragDepth
2269 	{
2270 		static const struct PrimitiveTopologyTable
2271 		{
2272 			std::string			name;
2273 			std::string			desc;
2274 			VkPrimitiveTopology	prim;
2275 		} primitiveTopologyTable[] =
2276 		{
2277 			{ "point_list",		"test that points respect gl_fragdepth", VK_PRIMITIVE_TOPOLOGY_POINT_LIST },
2278 			{ "line_list",		"test taht lines respect gl_fragdepth", VK_PRIMITIVE_TOPOLOGY_LINE_LIST },
2279 			{ "triangle_list",	"test that triangles respect gl_fragdepth", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP },
2280 		};
2281 
2282 		static const struct TestCaseTable
2283 		{
2284 			VkFormat				format;
2285 			std::string				name;
2286 			bool					largeDepthEnable;
2287 			bool					depthClampEnable;
2288 			VkSampleCountFlagBits	samples;
2289 		} testCaseTable[] =
2290 		{
2291 			{ VK_FORMAT_D16_UNORM,				"d16_unorm_no_depth_clamp",				false,	false,	VK_SAMPLE_COUNT_1_BIT },
2292 			{ VK_FORMAT_X8_D24_UNORM_PACK32,	"x8_d24_unorm_pack32_no_depth_clamp",	false,	false,	VK_SAMPLE_COUNT_1_BIT },
2293 			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat_no_depth_clamp",			false,	false,	VK_SAMPLE_COUNT_1_BIT },
2294 			{ VK_FORMAT_D16_UNORM_S8_UINT,		"d16_unorm_s8_uint_no_depth_clamp",		false,	false,	VK_SAMPLE_COUNT_1_BIT },
2295 			{ VK_FORMAT_D24_UNORM_S8_UINT,		"d24_unorm_s8_uint_no_depth_clamp",		false,	false,	VK_SAMPLE_COUNT_1_BIT },
2296 			{ VK_FORMAT_D32_SFLOAT_S8_UINT,		"d32_sfloat_s8_uint_no_depth_clamp",	false,	false,	VK_SAMPLE_COUNT_1_BIT },
2297 			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat_large_depth",				true,	false,	VK_SAMPLE_COUNT_1_BIT },
2298 			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat",							false,	true,	VK_SAMPLE_COUNT_1_BIT },
2299 			{ VK_FORMAT_D32_SFLOAT_S8_UINT,		"d32_sfloat_s8_uint",					false,	true,	VK_SAMPLE_COUNT_1_BIT },
2300 			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat_multisample_2",				false,	false,	VK_SAMPLE_COUNT_2_BIT },
2301 			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat_multisample_4",				false,	false,	VK_SAMPLE_COUNT_4_BIT },
2302 			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat_multisample_8",				false,	false,	VK_SAMPLE_COUNT_8_BIT },
2303 			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat_multisample_16",			false,	false,	VK_SAMPLE_COUNT_16_BIT },
2304 			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat_multisample_32",			false,	false,	VK_SAMPLE_COUNT_32_BIT },
2305 			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat_multisample_64",			false,	false,	VK_SAMPLE_COUNT_64_BIT },
2306 		};
2307 
2308 		for (deUint32 primNdx = 0;  primNdx < DE_LENGTH_OF_ARRAY(primitiveTopologyTable); primNdx++)
2309 		{
2310 			for (deUint32 caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(testCaseTable); caseNdx++)
2311 				fragDepthGroup->addChild(new BuiltinFragDepthCase(testCtx, (primitiveTopologyTable[primNdx].name+"_" + testCaseTable[caseNdx].name).c_str(), primitiveTopologyTable[primNdx].desc.c_str(),
2312 							primitiveTopologyTable[primNdx].prim, testCaseTable[caseNdx].format, testCaseTable[caseNdx].largeDepthEnable, testCaseTable[caseNdx].depthClampEnable, testCaseTable[caseNdx].samples));
2313 
2314 		}
2315 	}
2316 
2317 	builtinGroup->addChild(frontFacingGroup.release());
2318 	builtinGroup->addChild(fragDepthGroup.release());
2319 	builtinGroup->addChild(fragCoordMsaaGroup.release());
2320 	builtinGroup->addChild(simpleGroup.release());
2321 
2322 	for (deUint16 shaderType = 0; shaderType <= (SHADER_INPUT_BUILTIN_BIT | SHADER_INPUT_VARYING_BIT | SHADER_INPUT_CONSTANT_BIT); ++shaderType)
2323 	{
2324 		inputVariationsGroup->addChild(new BuiltinInputVariationsCase(testCtx, shaderInputTypeToString(shaderType), "Input variation test", shaderType));
2325 	}
2326 
2327 	builtinGroup->addChild(inputVariationsGroup.release());
2328 	return builtinGroup.release();
2329 }
2330 
2331 } // sr
2332 } // vkt
2333