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