1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Imagination Technologies Ltd.
7 * Copyright (c) 2023 LunarG, Inc.
8 * Copyright (c) 2023 Nintendo
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 *      http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 *
22 *//*!
23 * \file
24 * \brief Depth Tests
25 *//*--------------------------------------------------------------------*/
26
27#include "vktPipelineDepthTests.hpp"
28#include "vktPipelineClearUtil.hpp"
29#include "vktPipelineImageUtil.hpp"
30#include "vktPipelineVertexUtil.hpp"
31#include "vktPipelineReferenceRenderer.hpp"
32#include "vktTestCase.hpp"
33#include "vktTestCaseUtil.hpp"
34#include "vkImageUtil.hpp"
35#include "vkMemUtil.hpp"
36#include "vkPrograms.hpp"
37#include "vkQueryUtil.hpp"
38#include "vkRef.hpp"
39#include "vkRefUtil.hpp"
40#include "vkTypeUtil.hpp"
41#include "vkCmdUtil.hpp"
42#include "vkObjUtil.hpp"
43#include "tcuImageCompare.hpp"
44#include "deUniquePtr.hpp"
45#include "deStringUtil.hpp"
46#include "deMemory.h"
47
48#include <sstream>
49#include <vector>
50
51namespace vkt
52{
53namespace pipeline
54{
55
56using namespace vk;
57
58namespace
59{
60
61enum class DepthClipControlCase
62{
63	DISABLED			= 0,	// No depth clip control.
64	NORMAL				= 1,	// Depth clip control with static viewport.
65	NORMAL_W			= 2,	// Depth clip control with static viewport and .w different from 1.0f
66	BEFORE_STATIC		= 3,	// Set dynamic viewport state, then bind a static pipeline.
67	BEFORE_DYNAMIC		= 4,	// Set dynamic viewport state, bind dynamic pipeline.
68	BEFORE_TWO_DYNAMICS	= 5,	// Set dynamic viewport state, bind dynamic pipeline with [0,1] view volume, then bind dynamic pipeline with [-1,1] view volume.
69	AFTER_DYNAMIC		= 6,	// Bind dynamic pipeline, then set dynamic viewport state.
70};
71
72bool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, VkPhysicalDevice device, VkFormat format)
73{
74	VkFormatProperties formatProps;
75
76	instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
77
78	return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0u;
79}
80
81tcu::TestStatus testSupportsDepthStencilFormat (Context& context, VkFormat format)
82{
83	DE_ASSERT(vk::isDepthStencilFormat(format));
84
85	if (isSupportedDepthStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice(), format))
86		return tcu::TestStatus::pass("Format can be used in depth/stencil attachment");
87	else
88		return tcu::TestStatus::fail("Unsupported depth/stencil attachment format");
89}
90
91tcu::TestStatus testSupportsAtLeastOneDepthStencilFormat (Context& context, const std::vector<VkFormat> formats)
92{
93	std::ostringstream	supportedFormatsMsg;
94	bool				pass					= false;
95
96	DE_ASSERT(!formats.empty());
97
98	for (size_t formatNdx = 0; formatNdx < formats.size(); formatNdx++)
99	{
100		const VkFormat format = formats[formatNdx];
101
102		DE_ASSERT(vk::isDepthStencilFormat(format));
103
104		if (isSupportedDepthStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice(), format))
105		{
106			pass = true;
107			supportedFormatsMsg << vk::getFormatName(format);
108
109			if (formatNdx < formats.size() - 1)
110				supportedFormatsMsg << ", ";
111		}
112	}
113
114	if (pass)
115		return tcu::TestStatus::pass(std::string("Supported depth/stencil formats: ") + supportedFormatsMsg.str());
116	else
117		return tcu::TestStatus::fail("All depth/stencil formats are unsupported");
118}
119
120class DepthTest : public vkt::TestCase
121{
122public:
123	enum
124	{
125		QUAD_COUNT = 4
126	};
127
128	static const float					quadDepths[QUAD_COUNT];
129	static const float					quadDepthsMinusOneToOne[QUAD_COUNT];
130	static const float					quadWs[QUAD_COUNT];
131
132										DepthTest				(tcu::TestContext&					testContext,
133																 const std::string&					name,
134																 const PipelineConstructionType		pipelineConstructionType,
135																 const VkFormat						depthFormat,
136																 const VkCompareOp					depthCompareOps[QUAD_COUNT],
137																 const bool							separateDepthStencilLayouts,
138																 const VkPrimitiveTopology			primitiveTopology				= VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
139																 const bool							depthBoundsTestEnable			= false,
140																 const float						depthBoundsMin					= 0.0f,
141																 const float						depthBoundsMax					= 1.0f,
142																 const bool							depthTestEnable					= true,
143																 const bool							stencilTestEnable				= false,
144																 const bool							colorAttachmentEnable			= true,
145																 const bool							hostVisible						= false,
146																 const tcu::UVec2					renderSize						= tcu::UVec2(32, 32),
147																 const DepthClipControlCase			depthClipControl				= DepthClipControlCase::DISABLED);
148	virtual								~DepthTest				(void);
149	virtual void						initPrograms			(SourceCollections& programCollection) const;
150	virtual void						checkSupport			(Context& context) const;
151	virtual TestInstance*				createInstance			(Context& context) const;
152
153private:
154	const PipelineConstructionType		m_pipelineConstructionType;
155	const VkFormat						m_depthFormat;
156	const bool							m_separateDepthStencilLayouts;
157	VkPrimitiveTopology					m_primitiveTopology;
158	const bool							m_depthBoundsTestEnable;
159	const float							m_depthBoundsMin;
160	const float							m_depthBoundsMax;
161	const bool							m_depthTestEnable;
162	const bool							m_stencilTestEnable;
163	const bool							m_colorAttachmentEnable;
164	const bool							m_hostVisible;
165	const tcu::UVec2					m_renderSize;
166	const DepthClipControlCase			m_depthClipControl;
167	VkCompareOp							m_depthCompareOps[QUAD_COUNT];
168};
169
170class DepthTestInstance : public vkt::TestInstance
171{
172public:
173										DepthTestInstance		(Context&							context,
174																 const PipelineConstructionType		pipelineConstructionType,
175																 const VkFormat						depthFormat,
176																 const VkCompareOp					depthCompareOps[DepthTest::QUAD_COUNT],
177																 const bool							separateDepthStencilLayouts,
178																 const VkPrimitiveTopology			primitiveTopology,
179																 const bool							depthBoundsTestEnable,
180																 const float						depthBoundsMin,
181																 const float						depthBoundsMax,
182																 const bool							depthTestEnable,
183																 const bool							stencilTestEnable,
184																 const bool							colorAttachmentEnable,
185																 const bool							hostVisible,
186																 const tcu::UVec2					renderSize,
187																 const DepthClipControlCase			depthClipControl);
188
189	virtual								~DepthTestInstance		(void);
190	virtual tcu::TestStatus				iterate					(void);
191
192private:
193	tcu::TestStatus						verifyImage				(void);
194
195private:
196	VkCompareOp							m_depthCompareOps[DepthTest::QUAD_COUNT];
197	const tcu::UVec2					m_renderSize;
198	const VkFormat						m_colorFormat;
199	const VkFormat						m_depthFormat;
200	const bool							m_separateDepthStencilLayouts;
201	VkPrimitiveTopology					m_primitiveTopology;
202	const bool							m_depthBoundsTestEnable;
203	const float							m_depthBoundsMin;
204	const float							m_depthBoundsMax;
205	const bool							m_depthTestEnable;
206	const bool							m_stencilTestEnable;
207	const bool							m_colorAttachmentEnable;
208	const bool							m_hostVisible;
209	const DepthClipControlCase			m_depthClipControl;
210	VkImageSubresourceRange				m_depthImageSubresourceRange;
211
212	Move<VkImage>						m_colorImage;
213	de::MovePtr<Allocation>				m_colorImageAlloc;
214	Move<VkImage>						m_depthImage;
215	de::MovePtr<Allocation>				m_depthImageAlloc;
216	Move<VkImageView>					m_colorAttachmentView;
217	Move<VkImageView>					m_depthAttachmentView;
218	RenderPassWrapper					m_renderPass;
219	Move<VkFramebuffer>					m_framebuffer;
220
221	ShaderWrapper						m_vertexShaderModule;
222	ShaderWrapper						m_fragmentShaderModule;
223
224	Move<VkBuffer>						m_vertexBuffer;
225	std::vector<Vertex4RGBA>			m_vertices;
226	de::MovePtr<Allocation>				m_vertexBufferAlloc;
227
228	Move<VkBuffer>						m_altVertexBuffer;
229	std::vector<Vertex4RGBA>			m_altVertices;
230	de::MovePtr<Allocation>				m_altVertexBufferAlloc;
231
232	PipelineLayoutWrapper				m_pipelineLayout;
233	GraphicsPipelineWrapper				m_graphicsPipelines[DepthTest::QUAD_COUNT];
234	GraphicsPipelineWrapper				m_altGraphicsPipelines[DepthTest::QUAD_COUNT];
235
236	Move<VkCommandPool>					m_cmdPool;
237	Move<VkCommandBuffer>				m_cmdBuffer;
238};
239
240const float DepthTest::quadDepths[QUAD_COUNT] =
241{
242	0.1f,
243	0.0f,
244	0.3f,
245	0.2f
246};
247
248// Depth values suitable for the depth range of -1..1.
249const float DepthTest::quadDepthsMinusOneToOne[QUAD_COUNT] =
250{
251	-0.8f,
252	-1.0f,
253	 0.6f,
254	 0.2f
255};
256
257const float DepthTest::quadWs[QUAD_COUNT] =
258{
259	2.0f,
260	1.25f,
261	0.5f,
262	0.25f
263};
264
265DepthTest::DepthTest (tcu::TestContext&					testContext,
266					  const std::string&				name,
267					  const PipelineConstructionType	pipelineConstructionType,
268					  const VkFormat					depthFormat,
269					  const VkCompareOp					depthCompareOps[QUAD_COUNT],
270					  const bool						separateDepthStencilLayouts,
271					  const VkPrimitiveTopology			primitiveTopology,
272					  const bool						depthBoundsTestEnable,
273					  const float						depthBoundsMin,
274					  const float						depthBoundsMax,
275					  const bool						depthTestEnable,
276					  const bool						stencilTestEnable,
277					  const bool						colorAttachmentEnable,
278					  const bool						hostVisible,
279						const tcu::UVec2				renderSize,
280					  const DepthClipControlCase		depthClipControl)
281	: vkt::TestCase					(testContext, name)
282	, m_pipelineConstructionType	(pipelineConstructionType)
283	, m_depthFormat					(depthFormat)
284	, m_separateDepthStencilLayouts	(separateDepthStencilLayouts)
285	, m_primitiveTopology			(primitiveTopology)
286	, m_depthBoundsTestEnable		(depthBoundsTestEnable)
287	, m_depthBoundsMin				(depthBoundsMin)
288	, m_depthBoundsMax				(depthBoundsMax)
289	, m_depthTestEnable				(depthTestEnable)
290	, m_stencilTestEnable			(stencilTestEnable)
291	, m_colorAttachmentEnable		(colorAttachmentEnable)
292	, m_hostVisible					(hostVisible)
293	, m_renderSize					(renderSize)
294	, m_depthClipControl			(depthClipControl)
295{
296	deMemcpy(m_depthCompareOps, depthCompareOps, sizeof(VkCompareOp) * QUAD_COUNT);
297}
298
299DepthTest::~DepthTest (void)
300{
301}
302
303void DepthTest::checkSupport (Context& context) const
304{
305	if (m_depthBoundsTestEnable)
306		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_DEPTH_BOUNDS);
307
308	if (!isSupportedDepthStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice(), m_depthFormat))
309		throw tcu::NotSupportedError(std::string("Unsupported depth/stencil format: ") + getFormatName(m_depthFormat));
310
311	if (m_separateDepthStencilLayouts && !context.isDeviceFunctionalitySupported("VK_KHR_separate_depth_stencil_layouts"))
312		TCU_THROW(NotSupportedError, "VK_KHR_separate_depth_stencil_layouts is not supported");
313
314	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_pipelineConstructionType);
315
316#ifndef CTS_USES_VULKANSC
317	if (m_depthClipControl != DepthClipControlCase::DISABLED && !context.isDeviceFunctionalitySupported("VK_EXT_depth_clip_control"))
318		TCU_THROW(NotSupportedError, "VK_EXT_depth_clip_control is not supported");
319#endif // CTS_USES_VULKANSC
320}
321
322TestInstance* DepthTest::createInstance (Context& context) const
323{
324	return new DepthTestInstance(context, m_pipelineConstructionType, m_depthFormat, m_depthCompareOps, m_separateDepthStencilLayouts, m_primitiveTopology, m_depthBoundsTestEnable, m_depthBoundsMin, m_depthBoundsMax, m_depthTestEnable, m_stencilTestEnable, m_colorAttachmentEnable, m_hostVisible, m_renderSize, m_depthClipControl);
325}
326
327void DepthTest::initPrograms (SourceCollections& programCollection) const
328{
329	if (m_colorAttachmentEnable)
330	{
331		programCollection.glslSources.add("color_vert") << glu::VertexSource(
332			"#version 310 es\n"
333			"layout(location = 0) in vec4 position;\n"
334			"layout(location = 1) in vec4 color;\n"
335			"layout(location = 0) out highp vec4 vtxColor;\n"
336			"void main (void)\n"
337			"{\n"
338			"	gl_Position = position;\n"
339			"	gl_PointSize = 1.0f;\n"
340			"	vtxColor = color;\n"
341			"}\n");
342
343		programCollection.glslSources.add("color_frag") << glu::FragmentSource(
344			"#version 310 es\n"
345			"layout(location = 0) in highp vec4 vtxColor;\n"
346			"layout(location = 0) out highp vec4 fragColor;\n"
347			"void main (void)\n"
348			"{\n"
349			"	fragColor = vtxColor;\n"
350			"}\n");
351	}
352	else
353	{
354		programCollection.glslSources.add("color_vert") << glu::VertexSource(
355			"#version 310 es\n"
356			"layout(location = 0) in vec4 position;\n"
357			"layout(location = 1) in vec4 color;\n"
358			"void main (void)\n"
359			"{\n"
360			"	gl_Position = position;\n"
361			"	gl_PointSize = 1.0f;\n"
362			"}\n");
363	}
364}
365
366DepthTestInstance::DepthTestInstance (Context&							context,
367									  const PipelineConstructionType	pipelineConstructionType,
368									  const VkFormat					depthFormat,
369									  const VkCompareOp					depthCompareOps[DepthTest::QUAD_COUNT],
370									  const bool						separateDepthStencilLayouts,
371									  const VkPrimitiveTopology			primitiveTopology,
372									  const bool						depthBoundsTestEnable,
373									  const float						depthBoundsMin,
374									  const float						depthBoundsMax,
375									  const bool						depthTestEnable,
376									  const bool						stencilTestEnable,
377									  const bool						colorAttachmentEnable,
378									  const bool						hostVisible,
379									  const tcu::UVec2					renderSize,
380									  const DepthClipControlCase		depthClipControl)
381	: vkt::TestInstance				(context)
382	, m_renderSize					(renderSize)
383	, m_colorFormat					(colorAttachmentEnable ? VK_FORMAT_R8G8B8A8_UNORM : VK_FORMAT_UNDEFINED)
384	, m_depthFormat					(depthFormat)
385	, m_separateDepthStencilLayouts	(separateDepthStencilLayouts)
386	, m_primitiveTopology			(primitiveTopology)
387	, m_depthBoundsTestEnable		(depthBoundsTestEnable)
388	, m_depthBoundsMin				(depthBoundsMin)
389	, m_depthBoundsMax				(depthBoundsMax)
390	, m_depthTestEnable				(depthTestEnable)
391	, m_stencilTestEnable			(stencilTestEnable)
392	, m_colorAttachmentEnable		(colorAttachmentEnable)
393	, m_hostVisible					(hostVisible)
394	, m_depthClipControl			(depthClipControl)
395	, m_graphicsPipelines
396	{
397		{ context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType },
398		{ context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType },
399		{ context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType },
400		{ context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType }
401	}
402	, m_altGraphicsPipelines
403	{
404		{ context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), m_context.getDeviceExtensions(), pipelineConstructionType },
405		{ context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), m_context.getDeviceExtensions(), pipelineConstructionType },
406		{ context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), m_context.getDeviceExtensions(), pipelineConstructionType },
407		{ context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), m_context.getDeviceExtensions(), pipelineConstructionType }
408	}
409{
410	const DeviceInterface&		vk						= context.getDeviceInterface();
411	const VkDevice				vkDevice				= context.getDevice();
412	const deUint32				queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
413	SimpleAllocator				memAlloc				(vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
414	const VkComponentMapping	componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
415	const bool					hasDepthClipControl		= (m_depthClipControl != DepthClipControlCase::DISABLED);
416	const bool					useAltGraphicsPipelines	= (m_depthClipControl == DepthClipControlCase::BEFORE_TWO_DYNAMICS ||
417														   m_depthClipControl == DepthClipControlCase::NORMAL_W);
418	const bool					useAltVertices			= m_depthClipControl == DepthClipControlCase::NORMAL_W;
419
420	// Copy depth operators
421	deMemcpy(m_depthCompareOps, depthCompareOps, sizeof(VkCompareOp) * DepthTest::QUAD_COUNT);
422
423	// Create color image
424	if (m_colorAttachmentEnable)
425	{
426		const VkImageCreateInfo colorImageParams =
427		{
428			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
429			DE_NULL,																	// const void*				pNext;
430			0u,																			// VkImageCreateFlags		flags;
431			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
432			m_colorFormat,																// VkFormat					format;
433			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D				extent;
434			1u,																			// deUint32					mipLevels;
435			1u,																			// deUint32					arrayLayers;
436			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
437			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
438			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
439			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
440			1u,																			// deUint32					queueFamilyIndexCount;
441			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
442			VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout			initialLayout;
443		};
444
445		m_colorImage			= createImage(vk, vkDevice, &colorImageParams);
446
447		// Allocate and bind color image memory
448		m_colorImageAlloc		= memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
449		VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
450	}
451
452	// Create depth image
453	{
454		const VkImageCreateInfo depthImageParams =
455		{
456			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType;
457			DE_NULL,										// const void*				pNext;
458			0u,												// VkImageCreateFlags		flags;
459			VK_IMAGE_TYPE_2D,								// VkImageType				imageType;
460			m_depthFormat,									// VkFormat					format;
461			{ m_renderSize.x(), m_renderSize.y(), 1u },		// VkExtent3D				extent;
462			1u,												// deUint32					mipLevels;
463			1u,												// deUint32					arrayLayers;
464			VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits	samples;
465			VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling;
466			VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
467			VK_IMAGE_USAGE_TRANSFER_SRC_BIT,				// VkImageUsageFlags		usage;
468			VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode;
469			1u,												// deUint32					queueFamilyIndexCount;
470			&queueFamilyIndex,								// const deUint32*			pQueueFamilyIndices;
471			VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			initialLayout;
472		};
473
474		m_depthImage = createImage(vk, vkDevice, &depthImageParams);
475
476		// Allocate and bind depth image memory
477		auto memReqs = MemoryRequirement::Local | MemoryRequirement::HostVisible;
478		m_depthImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_depthImage), m_hostVisible ? memReqs : MemoryRequirement::Any);
479		VK_CHECK(vk.bindImageMemory(vkDevice, *m_depthImage, m_depthImageAlloc->getMemory(), m_depthImageAlloc->getOffset()));
480
481		const VkImageAspectFlags aspect = (mapVkFormat(m_depthFormat).order == tcu::TextureFormat::DS ? VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT
482																									  : VK_IMAGE_ASPECT_DEPTH_BIT);
483		m_depthImageSubresourceRange    = makeImageSubresourceRange(aspect, 0u, depthImageParams.mipLevels, 0u, depthImageParams.arrayLayers);
484	}
485
486	// Create color attachment view
487	if (m_colorAttachmentEnable)
488	{
489		const VkImageViewCreateInfo colorAttachmentViewParams =
490		{
491			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
492			DE_NULL,										// const void*				pNext;
493			0u,												// VkImageViewCreateFlags	flags;
494			*m_colorImage,									// VkImage					image;
495			VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType			viewType;
496			m_colorFormat,									// VkFormat					format;
497			componentMappingRGBA,							// VkComponentMapping		components;
498			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }	// VkImageSubresourceRange	subresourceRange;
499		};
500
501		m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
502	}
503
504	// Create depth attachment view
505	{
506		const VkImageViewCreateInfo depthAttachmentViewParams =
507		{
508			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
509			DE_NULL,										// const void*				pNext;
510			0u,												// VkImageViewCreateFlags	flags;
511			*m_depthImage,									// VkImage					image;
512			VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType			viewType;
513			m_depthFormat,									// VkFormat					format;
514			componentMappingRGBA,							// VkComponentMapping		components;
515			m_depthImageSubresourceRange,					// VkImageSubresourceRange	subresourceRange;
516		};
517
518		m_depthAttachmentView = createImageView(vk, vkDevice, &depthAttachmentViewParams);
519	}
520
521	// Create render pass
522	m_renderPass = RenderPassWrapper(pipelineConstructionType, vk, vkDevice, m_colorFormat, m_depthFormat);
523
524	// Create framebuffer
525	{
526		std::vector<VkImage>			images;
527		std::vector<VkImageView>		attachmentBindInfos;
528
529		if (m_colorAttachmentEnable)
530		{
531			images.push_back(*m_colorImage);
532			attachmentBindInfos.push_back(*m_colorAttachmentView);
533		}
534
535		images.push_back(*m_depthImage);
536		attachmentBindInfos.push_back(*m_depthAttachmentView);
537
538		const VkFramebufferCreateInfo	framebufferParams	=
539		{
540			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType				sType;
541			DE_NULL,											// const void*					pNext;
542			0u,													// VkFramebufferCreateFlags		flags;
543			*m_renderPass,										// VkRenderPass					renderPass;
544			(deUint32)attachmentBindInfos.size(),				// deUint32						attachmentCount;
545			attachmentBindInfos.data(),							// const VkImageView*			pAttachments;
546			(deUint32)m_renderSize.x(),							// deUint32						width;
547			(deUint32)m_renderSize.y(),							// deUint32						height;
548			1u													// deUint32						layers;
549		};
550
551		m_renderPass.createFramebuffer(vk, vkDevice, &framebufferParams, images);
552	}
553
554	// Create pipeline layout
555	{
556		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
557		{
558			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
559			DE_NULL,											// const void*						pNext;
560			0u,													// VkPipelineLayoutCreateFlags		flags;
561			0u,													// deUint32							setLayoutCount;
562			DE_NULL,											// const VkDescriptorSetLayout*		pSetLayouts;
563			0u,													// deUint32							pushConstantRangeCount;
564			DE_NULL												// const VkPushConstantRange*		pPushConstantRanges;
565		};
566
567		m_pipelineLayout = PipelineLayoutWrapper(pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
568	}
569
570	// Shader modules
571	m_vertexShaderModule		= ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
572	if (m_colorAttachmentEnable)
573		m_fragmentShaderModule	= ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
574
575	const std::vector<VkViewport>	viewports		{ makeViewport(m_renderSize) };
576	const std::vector<VkViewport>	badViewports	{ makeViewport(0.0f, 0.0f, static_cast<float>(m_renderSize.x()) / 2.0f, static_cast<float>(m_renderSize.y()) / 2.0f, 1.0f, 0.0f) };
577	const std::vector<VkRect2D>		scissors		{ makeRect2D(m_renderSize) };
578	const bool						dynamicViewport	= (static_cast<int>(m_depthClipControl) > static_cast<int>(DepthClipControlCase::BEFORE_STATIC));
579
580	// Create pipeline
581	{
582		const VkVertexInputBindingDescription				vertexInputBindingDescription
583		{
584			0u,							// deUint32					binding;
585			sizeof(Vertex4RGBA),		// deUint32					strideInBytes;
586			VK_VERTEX_INPUT_RATE_VERTEX	// VkVertexInputStepRate	inputRate;
587		};
588
589		const VkVertexInputAttributeDescription				vertexInputAttributeDescriptions[2]
590		{
591			{
592				0u,									// deUint32	location;
593				0u,									// deUint32	binding;
594				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
595				0u									// deUint32	offset;
596			},
597			{
598				1u,									// deUint32	location;
599				0u,									// deUint32	binding;
600				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
601				DE_OFFSET_OF(Vertex4RGBA, color),	// deUint32	offset;
602			}
603		};
604
605		const VkPipelineVertexInputStateCreateInfo			vertexInputStateParams
606		{
607			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
608			DE_NULL,														// const void*								pNext;
609			0u,																// VkPipelineVertexInputStateCreateFlags	flags;
610			1u,																// deUint32									vertexBindingDescriptionCount;
611			&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
612			2u,																// deUint32									vertexAttributeDescriptionCount;
613			vertexInputAttributeDescriptions								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
614		};
615
616		const VkPipelineInputAssemblyStateCreateInfo		inputAssemblyStateParams
617		{
618			VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType								sType
619			DE_NULL,														// const void*									pNext
620			0u,																// VkPipelineInputAssemblyStateCreateFlags		flags
621			m_primitiveTopology,											// VkPrimitiveTopology							topology
622			VK_FALSE														// VkBool32										primitiveRestartEnable
623		};
624
625		VkPipelineDepthStencilStateCreateInfo				depthStencilStateParams
626		{
627			VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
628			DE_NULL,													// const void*								pNext;
629			0u,															// VkPipelineDepthStencilStateCreateFlags	flags;
630			m_depthTestEnable,											// VkBool32									depthTestEnable;
631			true,														// VkBool32									depthWriteEnable;
632			VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
633			m_depthBoundsTestEnable,									// VkBool32									depthBoundsTestEnable;
634			m_stencilTestEnable,										// VkBool32									stencilTestEnable;
635			// VkStencilOpState	front;
636			{
637				VK_STENCIL_OP_KEEP,		// VkStencilOp	failOp;
638				VK_STENCIL_OP_KEEP,		// VkStencilOp	passOp;
639				VK_STENCIL_OP_KEEP,		// VkStencilOp	depthFailOp;
640				VK_COMPARE_OP_NEVER,	// VkCompareOp	compareOp;
641				0u,						// deUint32		compareMask;
642				0u,						// deUint32		writeMask;
643				0u,						// deUint32		reference;
644			},
645			// VkStencilOpState	back;
646			{
647				VK_STENCIL_OP_KEEP,		// VkStencilOp	failOp;
648				VK_STENCIL_OP_KEEP,		// VkStencilOp	passOp;
649				VK_STENCIL_OP_KEEP,		// VkStencilOp	depthFailOp;
650				VK_COMPARE_OP_NEVER,	// VkCompareOp	compareOp;
651				0u,						// deUint32		compareMask;
652				0u,						// deUint32		writeMask;
653				0u,						// deUint32		reference;
654			},
655			m_depthBoundsMin,											// float									minDepthBounds;
656			m_depthBoundsMax,											// float									maxDepthBounds;
657		};
658
659		// Make sure rasterization is not disabled when the fragment shader is missing.
660		const vk::VkPipelineRasterizationStateCreateInfo rasterizationStateParams
661		{
662			vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	//	VkStructureType							sType;
663			nullptr,														//	const void*								pNext;
664			0u,																//	VkPipelineRasterizationStateCreateFlags	flags;
665			VK_FALSE,														//	VkBool32								depthClampEnable;
666			VK_FALSE,														//	VkBool32								rasterizerDiscardEnable;
667			vk::VK_POLYGON_MODE_FILL,										//	VkPolygonMode							polygonMode;
668			vk::VK_CULL_MODE_NONE,											//	VkCullModeFlags							cullMode;
669			vk::VK_FRONT_FACE_COUNTER_CLOCKWISE,							//	VkFrontFace								frontFace;
670			VK_FALSE,														//	VkBool32								depthBiasEnable;
671			0.0f,															//	float									depthBiasConstantFactor;
672			0.0f,															//	float									depthBiasClamp;
673			0.0f,															//	float									depthBiasSlopeFactor;
674			1.0f,															//	float									lineWidth;
675		};
676
677		PipelineViewportDepthClipControlCreateInfoWrapper depthClipControlWrapper;
678		PipelineViewportDepthClipControlCreateInfoWrapper depthClipControl01Wrapper;
679
680#ifndef CTS_USES_VULKANSC
681		VkPipelineViewportDepthClipControlCreateInfoEXT depthClipControlCreateInfo
682		{
683			VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT,	// VkStructureType	sType;
684			DE_NULL,																// const void*		pNext;
685			VK_TRUE,																// VkBool32			negativeOneToOne;
686		};
687		if (hasDepthClipControl)
688			depthClipControlWrapper.ptr = &depthClipControlCreateInfo;
689
690		// Using the range 0,1 in the structure.
691		VkPipelineViewportDepthClipControlCreateInfoEXT depthClipControlCreateInfo01
692		{
693			VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT,	// VkStructureType	sType;
694			DE_NULL,																// const void*		pNext;
695			VK_FALSE,																// VkBool32			negativeOneToOne;
696		};
697		depthClipControl01Wrapper.ptr = &depthClipControlCreateInfo01;
698#endif // CTS_USES_VULKANSC
699
700		// Dynamic viewport if needed.
701		std::vector<VkDynamicState> dynamicStates;
702
703		if (m_depthClipControl == DepthClipControlCase::BEFORE_DYNAMIC
704			|| m_depthClipControl == DepthClipControlCase::BEFORE_TWO_DYNAMICS
705			|| m_depthClipControl == DepthClipControlCase::AFTER_DYNAMIC)
706		{
707			dynamicStates.push_back(VK_DYNAMIC_STATE_VIEWPORT);
708		}
709
710		const VkPipelineDynamicStateCreateInfo					dynamicStateCreateInfo			=
711		{
712			VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,	//	VkStructureType						sType;
713			nullptr,												//	const void*							pNext;
714			0u,														//	VkPipelineDynamicStateCreateFlags	flags;
715			static_cast<uint32_t>(dynamicStates.size()),			//	uint32_t							dynamicStateCount;
716			de::dataOrNull(dynamicStates),							//	const VkDynamicState*				pDynamicStates;
717		};
718
719		const vk::VkPipelineColorBlendAttachmentState blendState
720		{
721			VK_FALSE,
722			VK_BLEND_FACTOR_ONE,
723			VK_BLEND_FACTOR_ONE,
724			VK_BLEND_OP_ADD,
725			VK_BLEND_FACTOR_ONE,
726			VK_BLEND_FACTOR_ONE,
727			VK_BLEND_OP_ADD,
728			VK_COLOR_COMPONENT_R_BIT |
729			VK_COLOR_COMPONENT_G_BIT |
730			VK_COLOR_COMPONENT_B_BIT |
731			VK_COLOR_COMPONENT_A_BIT,
732		};
733
734		deUint32 colorAttachmentCount = (m_colorFormat != VK_FORMAT_UNDEFINED) ? 1u : 0u;
735
736		const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo
737		{
738			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,		// VkStructureType								sType
739			DE_NULL,														// const void*									pNext
740			0u,																// VkPipelineColorBlendStateCreateFlags			flags
741			VK_FALSE,														// VkBool32										logicOpEnable
742			VK_LOGIC_OP_CLEAR,												// VkLogicOp									logicOp
743			colorAttachmentCount,											// deUint32										attachmentCount
744			&blendState,													// const VkPipelineColorBlendAttachmentState*	pAttachments
745			{ 0.0f, 0.0f, 0.0f, 0.0f }										// float										blendConstants[4]
746		};
747
748		for (int quadNdx = 0; quadNdx < DepthTest::QUAD_COUNT; quadNdx++)
749		{
750			depthStencilStateParams.depthCompareOp	= depthCompareOps[quadNdx];
751
752			m_graphicsPipelines[quadNdx].setDefaultMultisampleState()
753										.setDefaultColorBlendState()
754										.setViewportStatePnext(depthClipControlWrapper.ptr)
755										.setDynamicState(&dynamicStateCreateInfo)
756										.setupVertexInputState(&vertexInputStateParams, &inputAssemblyStateParams)
757										.setupPreRasterizationShaderState((dynamicViewport ? badViewports : viewports),
758																	scissors,
759																	m_pipelineLayout,
760																	*m_renderPass,
761																	0u,
762																	m_vertexShaderModule,
763																	&rasterizationStateParams)
764										.setupFragmentShaderState(m_pipelineLayout,
765																	*m_renderPass,
766																	0u,
767																	m_fragmentShaderModule,
768																	&depthStencilStateParams)
769										.setupFragmentOutputState(*m_renderPass, 0u, &colorBlendStateCreateInfo)
770										.setMonolithicPipelineLayout(m_pipelineLayout)
771										.buildPipeline();
772
773			if (useAltGraphicsPipelines)
774			{
775				if (m_depthClipControl == DepthClipControlCase::NORMAL_W)
776				{
777					m_altGraphicsPipelines[quadNdx].setDefaultMultisampleState()
778												   .setDefaultColorBlendState()
779												   .setViewportStatePnext(depthClipControl01Wrapper.ptr)
780												   .setDynamicState(&dynamicStateCreateInfo)
781												   .setupVertexInputState(&vertexInputStateParams, &inputAssemblyStateParams)
782												   .setupPreRasterizationShaderState((dynamicViewport ? badViewports : viewports),
783																				scissors,
784																				m_pipelineLayout,
785																				*m_renderPass,
786																				0u,
787																				m_vertexShaderModule,
788																				&rasterizationStateParams)
789												   .setupFragmentShaderState(m_pipelineLayout,
790																		*m_renderPass,
791																		0u,
792																		m_fragmentShaderModule,
793																		&depthStencilStateParams)
794												   .setupFragmentOutputState(*m_renderPass, 0u, &colorBlendStateCreateInfo)
795												   .setMonolithicPipelineLayout(m_pipelineLayout)
796												   .buildPipeline();
797				}
798				else
799				{
800					m_altGraphicsPipelines[quadNdx].setDefaultMultisampleState()
801												   .setDefaultColorBlendState()
802												   .setViewportStatePnext(depthClipControl01Wrapper.ptr)
803												   .setDynamicState(&dynamicStateCreateInfo)
804												   .setupVertexInputState(&vertexInputStateParams)
805												   .setupPreRasterizationShaderState((dynamicViewport ? badViewports : viewports),
806																					scissors,
807																					m_pipelineLayout,
808																					*m_renderPass,
809																					0u,
810																					m_vertexShaderModule,
811																					&rasterizationStateParams)
812												   .setupFragmentShaderState(m_pipelineLayout,
813																					*m_renderPass,
814																					0u,
815																					m_fragmentShaderModule,
816																					&depthStencilStateParams)
817												   .setupFragmentOutputState(*m_renderPass, 0u, &colorBlendStateCreateInfo)
818												   .setMonolithicPipelineLayout(m_pipelineLayout)
819												   .buildPipeline();
820				}
821			}
822		}
823	}
824
825	// Create vertex buffer
826	{
827		const VkBufferCreateInfo vertexBufferParams =
828		{
829			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
830			DE_NULL,									// const void*			pNext;
831			0u,											// VkBufferCreateFlags	flags;
832			1024u,										// VkDeviceSize			size;
833			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
834			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
835			1u,											// deUint32				queueFamilyIndexCount;
836			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
837		};
838
839		m_vertices			= createOverlappingQuads();
840		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
841		m_vertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
842
843		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
844
845		if (useAltVertices) {
846			m_altVertices			= createOverlappingQuads();
847			m_altVertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
848			m_altVertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_altVertexBuffer), MemoryRequirement::HostVisible);
849
850			VK_CHECK(vk.bindBufferMemory(vkDevice, *m_altVertexBuffer, m_altVertexBufferAlloc->getMemory(), m_altVertexBufferAlloc->getOffset()));
851		}
852
853		// Adjust depths
854		for (int quadNdx = 0; quadNdx < DepthTest::QUAD_COUNT; quadNdx++)
855			for (int vertexNdx = 0; vertexNdx < 6; vertexNdx++)
856			{
857				m_vertices[quadNdx * 6 + vertexNdx].position.z() = (hasDepthClipControl ? DepthTest::quadDepthsMinusOneToOne[quadNdx] : DepthTest::quadDepths[quadNdx]);
858				if (m_depthClipControl == DepthClipControlCase::NORMAL_W)
859				{
860					const float w = DepthTest::quadWs[quadNdx];
861					m_vertices[quadNdx * 6 + vertexNdx].position.x() *= w;
862					m_vertices[quadNdx * 6 + vertexNdx].position.y() *= w;
863					m_vertices[quadNdx * 6 + vertexNdx].position.z() *= w;
864					m_vertices[quadNdx * 6 + vertexNdx].position.w() = w;
865				}
866				if (useAltVertices)
867				{
868					m_altVertices[quadNdx * 6 + vertexNdx].position = m_vertices[quadNdx * 6 + vertexNdx].position;
869					float z = m_altVertices[quadNdx * 6 + vertexNdx].position.z();
870					float w = m_altVertices[quadNdx * 6 + vertexNdx].position.w();
871					if (depthCompareOps[quadNdx] == vk::VK_COMPARE_OP_NOT_EQUAL ||
872						depthCompareOps[quadNdx] == vk::VK_COMPARE_OP_LESS ||
873						depthCompareOps[quadNdx] == vk::VK_COMPARE_OP_LESS_OR_EQUAL)
874					{
875						z += 0.01f;
876					}
877					else if (depthCompareOps[quadNdx] == vk::VK_COMPARE_OP_GREATER ||
878							 depthCompareOps[quadNdx] == vk::VK_COMPARE_OP_GREATER_OR_EQUAL)
879					{
880						z -= 0.01f;
881					}
882					m_altVertices[quadNdx * 6 + vertexNdx].position.z() = (z + w) * 0.5f;
883				}
884			}
885
886		// Load vertices into vertex buffer
887		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
888		flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
889
890		if (useAltVertices) {
891			deMemcpy(m_altVertexBufferAlloc->getHostPtr(), m_altVertices.data(), m_altVertices.size() * sizeof(Vertex4RGBA));
892			flushAlloc(vk, vkDevice, *m_altVertexBufferAlloc);
893		}
894	}
895
896	// Create command pool
897	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
898
899	// Create command buffer
900	{
901		std::vector<VkClearValue>			attachmentClearValues;
902
903		if (m_colorAttachmentEnable)
904			attachmentClearValues.push_back(defaultClearValue(m_colorFormat));
905
906		attachmentClearValues.push_back(defaultClearValue(m_depthFormat));
907
908		const VkImageMemoryBarrier			colorBarrier					=
909		{
910			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,									// VkStructureType            sType;
911			DE_NULL,																// const void*                pNext;
912			(VkAccessFlags)0,														// VkAccessFlags              srcAccessMask;
913			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,									// VkAccessFlags              dstAccessMask;
914			VK_IMAGE_LAYOUT_UNDEFINED,												// VkImageLayout              oldLayout;
915			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,								// VkImageLayout              newLayout;
916			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   srcQueueFamilyIndex;
917			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   dstQueueFamilyIndex;
918			*m_colorImage,															// VkImage                    image;
919			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }							// VkImageSubresourceRange    subresourceRange;
920		};
921
922		VkImageSubresourceRange				depthBarrierSubresourceRange	= m_depthImageSubresourceRange;
923		VkImageLayout						newLayout						= VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
924		if (m_separateDepthStencilLayouts)
925		{
926			depthBarrierSubresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
927			newLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
928		}
929
930		const VkImageMemoryBarrier			depthBarrier					=
931		{
932			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,									// VkStructureType            sType;
933			DE_NULL,																// const void*                pNext;
934			(VkAccessFlags)0,														// VkAccessFlags              srcAccessMask;
935			VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,							// VkAccessFlags              dstAccessMask;
936			VK_IMAGE_LAYOUT_UNDEFINED,												// VkImageLayout              oldLayout;
937			newLayout										,						// VkImageLayout              newLayout;
938			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   srcQueueFamilyIndex;
939			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   dstQueueFamilyIndex;
940			*m_depthImage,															// VkImage                    image;
941			depthBarrierSubresourceRange,											// VkImageSubresourceRange    subresourceRange;
942		};
943
944		std::vector<VkImageMemoryBarrier>	imageLayoutBarriers;
945
946		if (m_colorAttachmentEnable)
947			imageLayoutBarriers.push_back(colorBarrier);
948
949		imageLayoutBarriers.push_back(depthBarrier);
950
951		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
952
953		beginCommandBuffer(vk, *m_cmdBuffer, 0u);
954
955		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
956			VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, (VkDependencyFlags)0,
957			0u, DE_NULL, 0u, DE_NULL, (deUint32)imageLayoutBarriers.size(), imageLayoutBarriers.data());
958
959		m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), (deUint32)attachmentClearValues.size(), attachmentClearValues.data());
960
961		const VkDeviceSize quadOffset = (m_vertices.size() / DepthTest::QUAD_COUNT) * sizeof(Vertex4RGBA);
962
963		for (int quadNdx = 0; quadNdx < DepthTest::QUAD_COUNT; quadNdx++)
964		{
965			VkDeviceSize vertexBufferOffset = quadOffset * quadNdx;
966
967			if (m_depthClipControl == DepthClipControlCase::NORMAL_W && depthCompareOps[quadNdx] != vk::VK_COMPARE_OP_NEVER)
968			{
969				m_altGraphicsPipelines[quadNdx].bind(*m_cmdBuffer);
970				vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_altVertexBuffer.get(), &vertexBufferOffset);
971				vk.cmdDraw(*m_cmdBuffer, (deUint32)(m_altVertices.size() / DepthTest::QUAD_COUNT), 1, 0, 0);
972			}
973
974			if (m_depthClipControl == DepthClipControlCase::BEFORE_STATIC
975				|| m_depthClipControl == DepthClipControlCase::BEFORE_DYNAMIC
976				|| m_depthClipControl == DepthClipControlCase::BEFORE_TWO_DYNAMICS)
977			{
978				if (vk::isConstructionTypeShaderObject(pipelineConstructionType))
979				{
980#ifndef CTS_USES_VULKANSC
981					vk.cmdSetViewportWithCount(*m_cmdBuffer, 1u, viewports.data());
982#else
983					vk.cmdSetViewportWithCountEXT(*m_cmdBuffer, 1u, viewports.data());
984#endif
985				}
986				else
987				{
988					vk.cmdSetViewport(*m_cmdBuffer, 0u, 1u, viewports.data());
989				}
990			}
991
992			if (m_depthClipControl == DepthClipControlCase::BEFORE_TWO_DYNAMICS)
993				m_altGraphicsPipelines[quadNdx].bind(*m_cmdBuffer);
994			m_graphicsPipelines[quadNdx].bind(*m_cmdBuffer);
995
996			if (m_depthClipControl == DepthClipControlCase::AFTER_DYNAMIC)
997			{
998				if (vk::isConstructionTypeShaderObject(pipelineConstructionType))
999				{
1000#ifndef CTS_USES_VULKANSC
1001					vk.cmdSetViewportWithCount(*m_cmdBuffer, 1u, viewports.data());
1002#else
1003					vk.cmdSetViewportWithCountEXT(*m_cmdBuffer, 1u, viewports.data());
1004#endif
1005				}
1006				else
1007				{
1008					vk.cmdSetViewport(*m_cmdBuffer, 0u, 1u, viewports.data());
1009				}
1010			}
1011
1012			vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
1013			vk.cmdDraw(*m_cmdBuffer, (deUint32)(m_vertices.size() / DepthTest::QUAD_COUNT), 1, 0, 0);
1014		}
1015
1016		m_renderPass.end(vk, *m_cmdBuffer);
1017		endCommandBuffer(vk, *m_cmdBuffer);
1018	}
1019}
1020
1021DepthTestInstance::~DepthTestInstance (void)
1022{
1023}
1024
1025tcu::TestStatus DepthTestInstance::iterate (void)
1026{
1027	const DeviceInterface&		vk			= m_context.getDeviceInterface();
1028	const VkDevice				vkDevice	= m_context.getDevice();
1029	const VkQueue				queue		= m_context.getUniversalQueue();
1030
1031	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1032
1033	return verifyImage();
1034}
1035
1036tcu::TestStatus DepthTestInstance::verifyImage (void)
1037{
1038	const tcu::TextureFormat	tcuColorFormat	= mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM);
1039	const tcu::TextureFormat	tcuDepthFormat	= mapVkFormat(m_depthFormat);
1040	const ColorVertexShader		vertexShader;
1041	const ColorFragmentShader	fragmentShader	(tcuColorFormat, tcuDepthFormat, (m_depthClipControl != DepthClipControlCase::DISABLED));
1042	const rr::Program			program			(&vertexShader, &fragmentShader);
1043	ReferenceRenderer			refRenderer		(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
1044	bool						colorCompareOk	= false;
1045	bool						depthCompareOk	= false;
1046
1047	// Render reference image
1048	{
1049		for (int quadNdx = 0; quadNdx < DepthTest::QUAD_COUNT; quadNdx++)
1050		{
1051			// Set depth state
1052			rr::RenderState renderState(refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits);
1053			renderState.fragOps.depthTestEnabled = m_depthTestEnable;
1054			renderState.fragOps.depthFunc = mapVkCompareOp(m_depthCompareOps[quadNdx]);
1055			if (m_depthBoundsTestEnable)
1056			{
1057				renderState.fragOps.depthBoundsTestEnabled = true;
1058				renderState.fragOps.minDepthBound = m_depthBoundsMin;
1059				renderState.fragOps.maxDepthBound = m_depthBoundsMax;
1060			}
1061
1062			refRenderer.draw(renderState,
1063							 mapVkPrimitiveTopology(m_primitiveTopology),
1064							 std::vector<Vertex4RGBA>(m_vertices.begin() + quadNdx * 6,
1065													  m_vertices.begin() + (quadNdx + 1) * 6));
1066		}
1067	}
1068
1069	// Compare color result with reference image
1070	if (m_colorAttachmentEnable)
1071	{
1072		const DeviceInterface&			vk					= m_context.getDeviceInterface();
1073		const VkDevice					vkDevice			= m_context.getDevice();
1074		const VkQueue					queue				= m_context.getUniversalQueue();
1075		const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1076		SimpleAllocator					allocator			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1077		de::MovePtr<tcu::TextureLevel>	result				= readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize);
1078
1079		colorCompareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
1080															  "IntImageCompare",
1081															  "Image comparison",
1082															  refRenderer.getAccess(),
1083															  result->getAccess(),
1084															  tcu::UVec4(2, 2, 2, 2),
1085															  tcu::IVec3(1, 1, 0),
1086															  true,
1087															  tcu::COMPARE_LOG_RESULT);
1088	}
1089	else
1090	{
1091		colorCompareOk = true;
1092	}
1093
1094	// Compare depth result with reference image
1095	{
1096		const DeviceInterface&			vk					= m_context.getDeviceInterface();
1097		const VkDevice					vkDevice			= m_context.getDevice();
1098		const VkQueue					queue				= m_context.getUniversalQueue();
1099		const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1100		SimpleAllocator					allocator			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1101		de::MovePtr<tcu::TextureLevel>	result				= readDepthAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_depthImage, m_depthFormat, m_renderSize);
1102
1103		{
1104			de::MovePtr<tcu::TextureLevel>	convertedReferenceLevel;
1105			tcu::Maybe<tcu::TextureFormat>	convertedFormat;
1106
1107			if (refRenderer.getDepthStencilAccess().getFormat().type == tcu::TextureFormat::UNSIGNED_INT_24_8_REV)
1108			{
1109				convertedFormat = tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT24);
1110			}
1111			else if (refRenderer.getDepthStencilAccess().getFormat().type == tcu::TextureFormat::UNSIGNED_INT_16_8_8)
1112			{
1113				convertedFormat = tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT16);
1114			}
1115			else if (refRenderer.getDepthStencilAccess().getFormat().type == tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV)
1116			{
1117				convertedFormat = tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::FLOAT);
1118			}
1119
1120			if (convertedFormat)
1121			{
1122				convertedReferenceLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(*convertedFormat, refRenderer.getDepthStencilAccess().getSize().x(), refRenderer.getDepthStencilAccess().getSize().y()));
1123				tcu::copy(convertedReferenceLevel->getAccess(), refRenderer.getDepthStencilAccess());
1124			}
1125
1126			float depthThreshold = 0.0f;
1127
1128			if (tcu::getTextureChannelClass(result->getFormat().type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)
1129			{
1130				const tcu::IVec4	formatBits = tcu::getTextureFormatBitDepth(result->getFormat());
1131				depthThreshold = 1.0f / static_cast<float>((1 << formatBits[0]) - 1);
1132			}
1133			else if (tcu::getTextureChannelClass(result->getFormat().type) == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
1134			{
1135				depthThreshold = 0.0000001f;
1136			}
1137			else
1138				TCU_FAIL("unrecognized format type class");
1139
1140			depthCompareOk = tcu::floatThresholdCompare(m_context.getTestContext().getLog(),
1141														"DepthImageCompare",
1142														"Depth image comparison",
1143														convertedReferenceLevel ? convertedReferenceLevel->getAccess() : refRenderer.getDepthStencilAccess(),
1144														result->getAccess(),
1145														tcu::Vec4(depthThreshold, 0.0f, 0.0f, 0.0f),
1146														tcu::COMPARE_LOG_RESULT);
1147		}
1148	}
1149
1150	if (colorCompareOk && depthCompareOk)
1151		return tcu::TestStatus::pass("Result image matches reference");
1152	else
1153		return tcu::TestStatus::fail("Image mismatch");
1154}
1155
1156std::string getFormatCaseName (const VkFormat format)
1157{
1158	const std::string	fullName	= getFormatName(format);
1159
1160	DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
1161
1162	return de::toLower(fullName.substr(10));
1163}
1164
1165std::string getTopologyName (const VkPrimitiveTopology topology) {
1166	const std::string	fullName	= getPrimitiveTopologyName(topology);
1167
1168	DE_ASSERT(de::beginsWith(fullName, "VK_PRIMITIVE_TOPOLOGY_"));
1169
1170	return de::toLower(fullName.substr(22));
1171}
1172
1173std::string	getCompareOpsName (const VkCompareOp quadDepthOps[DepthTest::QUAD_COUNT])
1174{
1175	std::ostringstream name;
1176
1177	for (int quadNdx = 0; quadNdx < DepthTest::QUAD_COUNT; quadNdx++)
1178	{
1179		const std::string	fullOpName	= getCompareOpName(quadDepthOps[quadNdx]);
1180
1181		DE_ASSERT(de::beginsWith(fullOpName, "VK_COMPARE_OP_"));
1182
1183		name << de::toLower(fullOpName.substr(14));
1184
1185		if (quadNdx < DepthTest::QUAD_COUNT - 1)
1186			name << "_";
1187	}
1188
1189	return name.str();
1190}
1191
1192} // anonymous
1193
1194tcu::TestCaseGroup* createDepthTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
1195{
1196	const VkFormat			depthFormats[]						=
1197	{
1198		VK_FORMAT_D16_UNORM,
1199		VK_FORMAT_X8_D24_UNORM_PACK32,
1200		VK_FORMAT_D32_SFLOAT,
1201		VK_FORMAT_D16_UNORM_S8_UINT,
1202		VK_FORMAT_D24_UNORM_S8_UINT,
1203		VK_FORMAT_D32_SFLOAT_S8_UINT
1204	};
1205
1206	// Each entry configures the depth compare operators of QUAD_COUNT quads.
1207	// All entries cover pair-wise combinations of compare operators.
1208	const VkCompareOp		depthOps[][DepthTest::QUAD_COUNT]	=
1209	{
1210		{ VK_COMPARE_OP_NOT_EQUAL,			VK_COMPARE_OP_NOT_EQUAL,		VK_COMPARE_OP_NOT_EQUAL,		VK_COMPARE_OP_NOT_EQUAL },
1211		{ VK_COMPARE_OP_NOT_EQUAL,			VK_COMPARE_OP_EQUAL,			VK_COMPARE_OP_EQUAL,			VK_COMPARE_OP_GREATER },
1212		{ VK_COMPARE_OP_NOT_EQUAL,			VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_LESS_OR_EQUAL },
1213		{ VK_COMPARE_OP_NOT_EQUAL,			VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_GREATER_OR_EQUAL },
1214		{ VK_COMPARE_OP_NOT_EQUAL,			VK_COMPARE_OP_LESS_OR_EQUAL,	VK_COMPARE_OP_LESS_OR_EQUAL,	VK_COMPARE_OP_ALWAYS },
1215		{ VK_COMPARE_OP_NOT_EQUAL,			VK_COMPARE_OP_LESS,				VK_COMPARE_OP_LESS,				VK_COMPARE_OP_LESS },
1216		{ VK_COMPARE_OP_NOT_EQUAL,			VK_COMPARE_OP_NEVER,			VK_COMPARE_OP_NEVER,			VK_COMPARE_OP_NEVER },
1217		{ VK_COMPARE_OP_EQUAL,				VK_COMPARE_OP_NOT_EQUAL,		VK_COMPARE_OP_EQUAL,			VK_COMPARE_OP_EQUAL },
1218		{ VK_COMPARE_OP_EQUAL,				VK_COMPARE_OP_EQUAL,			VK_COMPARE_OP_NOT_EQUAL,		VK_COMPARE_OP_LESS },
1219		{ VK_COMPARE_OP_EQUAL,				VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_NOT_EQUAL },
1220		{ VK_COMPARE_OP_EQUAL,				VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_GREATER },
1221		{ VK_COMPARE_OP_EQUAL,				VK_COMPARE_OP_LESS_OR_EQUAL,	VK_COMPARE_OP_LESS,				VK_COMPARE_OP_LESS_OR_EQUAL },
1222		{ VK_COMPARE_OP_NOT_EQUAL,			VK_COMPARE_OP_ALWAYS,			VK_COMPARE_OP_ALWAYS,			VK_COMPARE_OP_EQUAL },
1223		{ VK_COMPARE_OP_EQUAL,				VK_COMPARE_OP_LESS,				VK_COMPARE_OP_NEVER,			VK_COMPARE_OP_ALWAYS },
1224		{ VK_COMPARE_OP_EQUAL,				VK_COMPARE_OP_NEVER,			VK_COMPARE_OP_LESS_OR_EQUAL,	VK_COMPARE_OP_GREATER_OR_EQUAL },
1225		{ VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_NOT_EQUAL,		VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_LESS },
1226		{ VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_EQUAL,			VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_ALWAYS },
1227		{ VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_NOT_EQUAL,		VK_COMPARE_OP_GREATER },
1228		{ VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_LESS_OR_EQUAL,	VK_COMPARE_OP_NOT_EQUAL },
1229		{ VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_LESS_OR_EQUAL,	VK_COMPARE_OP_NEVER,			VK_COMPARE_OP_GREATER_OR_EQUAL },
1230		{ VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_LESS,				VK_COMPARE_OP_EQUAL,			VK_COMPARE_OP_NEVER },
1231		{ VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_NOT_EQUAL,		VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_GREATER },
1232		{ VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_NEVER,			VK_COMPARE_OP_ALWAYS,			VK_COMPARE_OP_LESS_OR_EQUAL },
1233		{ VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_EQUAL,			VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_NOT_EQUAL },
1234		{ VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_EQUAL,			VK_COMPARE_OP_GREATER_OR_EQUAL },
1235		{ VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_NOT_EQUAL,		VK_COMPARE_OP_LESS_OR_EQUAL },
1236		{ VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_LESS_OR_EQUAL,	VK_COMPARE_OP_ALWAYS,			VK_COMPARE_OP_LESS },
1237		{ VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_LESS,				VK_COMPARE_OP_LESS_OR_EQUAL,	VK_COMPARE_OP_EQUAL },
1238		{ VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_ALWAYS,			VK_COMPARE_OP_LESS,				VK_COMPARE_OP_NEVER },
1239		{ VK_COMPARE_OP_LESS_OR_EQUAL,		VK_COMPARE_OP_NOT_EQUAL,		VK_COMPARE_OP_LESS_OR_EQUAL,	VK_COMPARE_OP_LESS_OR_EQUAL },
1240		{ VK_COMPARE_OP_LESS_OR_EQUAL,		VK_COMPARE_OP_EQUAL,			VK_COMPARE_OP_LESS,				VK_COMPARE_OP_EQUAL },
1241		{ VK_COMPARE_OP_LESS_OR_EQUAL,		VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_NEVER,			VK_COMPARE_OP_LESS },
1242		{ VK_COMPARE_OP_LESS_OR_EQUAL,		VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_EQUAL,			VK_COMPARE_OP_ALWAYS },
1243		{ VK_COMPARE_OP_LESS_OR_EQUAL,		VK_COMPARE_OP_LESS,				VK_COMPARE_OP_NOT_EQUAL,		VK_COMPARE_OP_GREATER_OR_EQUAL },
1244		{ VK_COMPARE_OP_LESS_OR_EQUAL,		VK_COMPARE_OP_LESS_OR_EQUAL,	VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_NEVER },
1245		{ VK_COMPARE_OP_LESS,				VK_COMPARE_OP_NOT_EQUAL,		VK_COMPARE_OP_LESS,				VK_COMPARE_OP_GREATER_OR_EQUAL },
1246		{ VK_COMPARE_OP_LESS,				VK_COMPARE_OP_EQUAL,			VK_COMPARE_OP_NEVER,			VK_COMPARE_OP_LESS_OR_EQUAL },
1247		{ VK_COMPARE_OP_LESS,				VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_LESS_OR_EQUAL,	VK_COMPARE_OP_NEVER },
1248		{ VK_COMPARE_OP_LESS,				VK_COMPARE_OP_LESS_OR_EQUAL,	VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_EQUAL },
1249		{ VK_COMPARE_OP_LESS,				VK_COMPARE_OP_LESS,				VK_COMPARE_OP_ALWAYS,			VK_COMPARE_OP_NOT_EQUAL },
1250		{ VK_COMPARE_OP_LESS,				VK_COMPARE_OP_NEVER,			VK_COMPARE_OP_NOT_EQUAL,		VK_COMPARE_OP_ALWAYS },
1251		{ VK_COMPARE_OP_NEVER,				VK_COMPARE_OP_NOT_EQUAL,		VK_COMPARE_OP_ALWAYS,			VK_COMPARE_OP_ALWAYS },
1252		{ VK_COMPARE_OP_LESS,				VK_COMPARE_OP_ALWAYS,			VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_LESS },
1253		{ VK_COMPARE_OP_NEVER,				VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_NEVER,			VK_COMPARE_OP_EQUAL },
1254		{ VK_COMPARE_OP_NEVER,				VK_COMPARE_OP_NEVER,			VK_COMPARE_OP_LESS,				VK_COMPARE_OP_GREATER },
1255		{ VK_COMPARE_OP_NEVER,				VK_COMPARE_OP_LESS_OR_EQUAL,	VK_COMPARE_OP_EQUAL,			VK_COMPARE_OP_NOT_EQUAL },
1256		{ VK_COMPARE_OP_NEVER,				VK_COMPARE_OP_LESS,				VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_LESS_OR_EQUAL },
1257		{ VK_COMPARE_OP_NEVER,				VK_COMPARE_OP_ALWAYS,			VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_GREATER_OR_EQUAL },
1258		{ VK_COMPARE_OP_ALWAYS,				VK_COMPARE_OP_EQUAL,			VK_COMPARE_OP_ALWAYS,			VK_COMPARE_OP_NEVER },
1259		{ VK_COMPARE_OP_ALWAYS,				VK_COMPARE_OP_NEVER,			VK_COMPARE_OP_EQUAL,			VK_COMPARE_OP_LESS },
1260		{ VK_COMPARE_OP_ALWAYS,				VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_LESS,				VK_COMPARE_OP_ALWAYS },
1261		{ VK_COMPARE_OP_ALWAYS,				VK_COMPARE_OP_ALWAYS,			VK_COMPARE_OP_NEVER,			VK_COMPARE_OP_GREATER },
1262		{ VK_COMPARE_OP_ALWAYS,				VK_COMPARE_OP_LESS_OR_EQUAL,	VK_COMPARE_OP_NOT_EQUAL,		VK_COMPARE_OP_EQUAL },
1263		{ VK_COMPARE_OP_LESS_OR_EQUAL,		VK_COMPARE_OP_NEVER,			VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_NOT_EQUAL },
1264		{ VK_COMPARE_OP_NEVER,				VK_COMPARE_OP_EQUAL,			VK_COMPARE_OP_LESS_OR_EQUAL,	VK_COMPARE_OP_LESS },
1265		{ VK_COMPARE_OP_EQUAL,				VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_ALWAYS,			VK_COMPARE_OP_NEVER },
1266		{ VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_ALWAYS,			VK_COMPARE_OP_LESS,				VK_COMPARE_OP_NOT_EQUAL },
1267		{ VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_NEVER,			VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_EQUAL },
1268		{ VK_COMPARE_OP_EQUAL,				VK_COMPARE_OP_ALWAYS,			VK_COMPARE_OP_EQUAL,			VK_COMPARE_OP_LESS_OR_EQUAL },
1269		{ VK_COMPARE_OP_LESS_OR_EQUAL,		VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_ALWAYS,			VK_COMPARE_OP_GREATER },
1270		{ VK_COMPARE_OP_NEVER,				VK_COMPARE_OP_NOT_EQUAL,		VK_COMPARE_OP_NOT_EQUAL,		VK_COMPARE_OP_NEVER },
1271		{ VK_COMPARE_OP_ALWAYS,				VK_COMPARE_OP_LESS,				VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_GREATER },
1272		{ VK_COMPARE_OP_ALWAYS,				VK_COMPARE_OP_NOT_EQUAL,		VK_COMPARE_OP_NEVER,			VK_COMPARE_OP_NOT_EQUAL },
1273		{ VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_ALWAYS,			VK_COMPARE_OP_NOT_EQUAL,		VK_COMPARE_OP_ALWAYS },
1274		{ VK_COMPARE_OP_LESS_OR_EQUAL,		VK_COMPARE_OP_ALWAYS,			VK_COMPARE_OP_LESS_OR_EQUAL,	VK_COMPARE_OP_GREATER },
1275		{ VK_COMPARE_OP_LESS,				VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_LESS,				VK_COMPARE_OP_GREATER },
1276		{ VK_COMPARE_OP_ALWAYS,				VK_COMPARE_OP_EQUAL,			VK_COMPARE_OP_LESS_OR_EQUAL,	VK_COMPARE_OP_GREATER_OR_EQUAL },
1277		{ VK_COMPARE_OP_ALWAYS,				VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_LESS_OR_EQUAL },
1278		{ VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_NEVER,			VK_COMPARE_OP_LESS },
1279		{ VK_COMPARE_OP_GREATER_OR_EQUAL,	VK_COMPARE_OP_NEVER,			VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_NEVER },
1280		{ VK_COMPARE_OP_LESS,				VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_EQUAL,			VK_COMPARE_OP_EQUAL },
1281		{ VK_COMPARE_OP_NEVER,				VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_ALWAYS,			VK_COMPARE_OP_GREATER_OR_EQUAL },
1282		{ VK_COMPARE_OP_NOT_EQUAL,			VK_COMPARE_OP_NOT_EQUAL,		VK_COMPARE_OP_GREATER,			VK_COMPARE_OP_ALWAYS },
1283		{ VK_COMPARE_OP_NOT_EQUAL,			VK_COMPARE_OP_LESS_OR_EQUAL,	VK_COMPARE_OP_NOT_EQUAL,		VK_COMPARE_OP_GREATER }
1284	};
1285
1286	const bool						colorAttachmentEnabled[]	= { true, false };
1287
1288	const VkPrimitiveTopology		primitiveTopologies[]		= { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, VK_PRIMITIVE_TOPOLOGY_LINE_LIST, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST };
1289
1290	de::MovePtr<tcu::TestCaseGroup>	depthTests					(new tcu::TestCaseGroup(testCtx, "depth"));
1291	de::MovePtr<tcu::TestCaseGroup>	noColorAttachmentTests		(new tcu::TestCaseGroup(testCtx, "nocolor"));
1292
1293	// Tests for format features
1294	if (!isConstructionTypeLibrary(pipelineConstructionType))
1295	{
1296		de::MovePtr<tcu::TestCaseGroup> formatFeaturesTests (new tcu::TestCaseGroup(testCtx, "format_features"));
1297
1298		// Formats that must be supported in all implementations
1299		addFunctionCase(formatFeaturesTests.get(),
1300				"support_d16_unorm",
1301				testSupportsDepthStencilFormat,
1302				VK_FORMAT_D16_UNORM);
1303
1304		// Sets where at least one of the formats must be supported
1305		const VkFormat	depthOnlyFormats[]		= { VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D32_SFLOAT };
1306		const VkFormat	depthStencilFormats[]	= { VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT };
1307
1308		addFunctionCase(formatFeaturesTests.get(),
1309				"support_d24_unorm_or_d32_sfloat",
1310				testSupportsAtLeastOneDepthStencilFormat,
1311				std::vector<VkFormat>(depthOnlyFormats, depthOnlyFormats + DE_LENGTH_OF_ARRAY(depthOnlyFormats)));
1312
1313		addFunctionCase(formatFeaturesTests.get(),
1314				"support_d24_unorm_s8_uint_or_d32_sfloat_s8_uint",
1315				testSupportsAtLeastOneDepthStencilFormat,
1316				std::vector<VkFormat>(depthStencilFormats, depthStencilFormats + DE_LENGTH_OF_ARRAY(depthStencilFormats)));
1317
1318		depthTests->addChild(formatFeaturesTests.release());
1319	}
1320
1321	for (deUint32 colorAttachmentEnabledIdx = 0; colorAttachmentEnabledIdx < DE_LENGTH_OF_ARRAY(colorAttachmentEnabled); colorAttachmentEnabledIdx++)
1322	{
1323		const bool colorEnabled = colorAttachmentEnabled[colorAttachmentEnabledIdx];
1324
1325		// Tests for format and compare operators
1326		{
1327			// Uses different depth formats
1328			de::MovePtr<tcu::TestCaseGroup> formatTests (new tcu::TestCaseGroup(testCtx, "format"));
1329
1330			for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(depthFormats); formatNdx++)
1331			{
1332				const bool		hasDepth					= tcu::hasDepthComponent(mapVkFormat(depthFormats[formatNdx]).order);
1333				const bool		hasStencil					= tcu::hasStencilComponent(mapVkFormat(depthFormats[formatNdx]).order);
1334				const int		separateLayoutsLoopCount	= (hasDepth && hasStencil) ? 2 : 1;
1335
1336				for (int separateDepthStencilLayouts = 0; separateDepthStencilLayouts < separateLayoutsLoopCount; ++separateDepthStencilLayouts)
1337				{
1338					const bool			useSeparateDepthStencilLayouts	= bool(separateDepthStencilLayouts);
1339
1340					de::MovePtr<tcu::TestCaseGroup>	formatTest		(new tcu::TestCaseGroup(testCtx,
1341								(getFormatCaseName(depthFormats[formatNdx]) + ((useSeparateDepthStencilLayouts) ? "_separate_layouts" : "")).c_str(),
1342								(std::string("Uses format ") + getFormatName(depthFormats[formatNdx]) + ((useSeparateDepthStencilLayouts) ? " with separate depth/stencil layouts" : "")).c_str()));
1343					de::MovePtr<tcu::TestCaseGroup>	compareOpsTests	(new tcu::TestCaseGroup(testCtx, "compare_ops", "Combines depth compare operators"));
1344
1345					for (size_t topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(primitiveTopologies); topologyNdx++) {
1346						const std::string topologyName = getTopologyName(primitiveTopologies[topologyNdx]) + "_";
1347						for (size_t opsNdx = 0; opsNdx < DE_LENGTH_OF_ARRAY(depthOps); opsNdx++)
1348						{
1349							compareOpsTests->addChild(new DepthTest(testCtx,
1350										topologyName + getCompareOpsName(depthOps[opsNdx]),
1351										pipelineConstructionType,
1352										depthFormats[formatNdx],
1353										depthOps[opsNdx],
1354										useSeparateDepthStencilLayouts,
1355										primitiveTopologies[topologyNdx],
1356										false,
1357										0.0f,
1358										1.0f));
1359
1360							compareOpsTests->addChild(new DepthTest(testCtx,
1361										topologyName + getCompareOpsName(depthOps[opsNdx]) + "_depth_bounds_test",
1362										pipelineConstructionType,
1363										depthFormats[formatNdx],
1364										depthOps[opsNdx],
1365										useSeparateDepthStencilLayouts,
1366										primitiveTopologies[topologyNdx],
1367										true,
1368										0.1f,
1369										0.25f,
1370										true,
1371										false,
1372										colorEnabled));
1373						}
1374					}
1375					// Special VkPipelineDepthStencilStateCreateInfo known to have issues
1376					{
1377						const VkCompareOp depthOpsSpecial[DepthTest::QUAD_COUNT] = { VK_COMPARE_OP_NEVER, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_NEVER };
1378
1379						compareOpsTests->addChild(new DepthTest(testCtx,
1380									"never_zerodepthbounds_depthdisabled_stencilenabled",
1381									pipelineConstructionType,
1382									depthFormats[formatNdx],
1383									depthOpsSpecial,
1384									useSeparateDepthStencilLayouts,
1385									VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
1386									true,
1387									0.0f,
1388									0.0f,
1389									false,
1390									true,
1391									colorEnabled));
1392					}
1393					formatTest->addChild(compareOpsTests.release());
1394
1395					// Test case with depth test enabled, but depth write disabled
1396					de::MovePtr<tcu::TestCaseGroup>	depthTestDisabled(new tcu::TestCaseGroup(testCtx, "depth_test_disabled"));
1397					{
1398						const VkCompareOp depthOpsDepthTestDisabled[DepthTest::QUAD_COUNT] = { VK_COMPARE_OP_NEVER, VK_COMPARE_OP_LESS, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_ALWAYS };
1399						depthTestDisabled->addChild(new DepthTest(testCtx,
1400									"depth_write_enabled",
1401									pipelineConstructionType,
1402									depthFormats[formatNdx],
1403									depthOpsDepthTestDisabled,
1404									useSeparateDepthStencilLayouts,
1405									VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
1406									false,			/* depthBoundsTestEnable */
1407									0.0f,			/* depthBoundMin*/
1408									1.0f,			/* depthBoundMax*/
1409									false,			/* depthTestEnable */
1410									false,			/* stencilTestEnable */
1411									colorEnabled	/* colorAttachmentEnable */));
1412					}
1413					formatTest->addChild(depthTestDisabled.release());
1414
1415					// Test case with depth buffer placed in local memory
1416					de::MovePtr<tcu::TestCaseGroup>	hostVisibleTests(new tcu::TestCaseGroup(testCtx, "host_visible", "Test for disabled depth test"));
1417					{
1418						const VkCompareOp hostVisibleOps[DepthTest::QUAD_COUNT] = { VK_COMPARE_OP_NEVER, VK_COMPARE_OP_LESS, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_ALWAYS };
1419
1420						// Depth buffer placed in local memory
1421						hostVisibleTests->addChild(new DepthTest(testCtx,
1422									"local_memory_depth_buffer",
1423									pipelineConstructionType,
1424									depthFormats[formatNdx],
1425									hostVisibleOps,
1426									useSeparateDepthStencilLayouts,
1427									VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
1428									false,					/* depthBoundsTestEnable */
1429									0.0f,					/* depthBoundMin*/
1430									1.0f,					/* depthBoundMax*/
1431									true,					/* depthTestEnable */
1432									false,					/* stencilTestEnable */
1433									colorEnabled,			/* colorAttachmentEnable */
1434									true,					/* hostVisible */
1435									tcu::UVec2(256, 256)	/*renderSize*/));
1436					}
1437
1438					formatTest->addChild(hostVisibleTests.release());
1439					formatTests->addChild(formatTest.release());
1440				}
1441			}
1442			if (colorEnabled)
1443				depthTests->addChild(formatTests.release());
1444			else
1445				noColorAttachmentTests->addChild(formatTests.release());
1446		}
1447	}
1448	depthTests->addChild(noColorAttachmentTests.release());
1449
1450#ifndef CTS_USES_VULKANSC
1451	de::MovePtr<tcu::TestCaseGroup>	depthClipControlTests		(new tcu::TestCaseGroup(testCtx, "depth_clip_control", "Depth tests with depth clip control enabled"));
1452	{
1453		const VkCompareOp compareOps[] = { VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_LESS };
1454
1455		const struct
1456		{
1457			const DepthClipControlCase	viewportCase;
1458			const std::string			suffix;
1459		} kViewportCases[] =
1460		{
1461			{ DepthClipControlCase::NORMAL,					""								},
1462			{ DepthClipControlCase::NORMAL_W,				"_different_w"					},
1463			{ DepthClipControlCase::BEFORE_STATIC,			"_viewport_before_static"		},
1464			{ DepthClipControlCase::BEFORE_DYNAMIC,			"_viewport_before_dynamic"		},
1465			{ DepthClipControlCase::BEFORE_TWO_DYNAMICS,	"_viewport_before_two_dynamic"	},
1466			{ DepthClipControlCase::AFTER_DYNAMIC,			"_viewport_after_dynamic"		},
1467		};
1468
1469		for (const auto& viewportCase : kViewportCases)
1470			for (const auto& format : depthFormats)
1471				for (const auto& compareOp : compareOps)
1472				{
1473					std::string testName = getFormatCaseName(format) + "_" + de::toLower(std::string(getCompareOpName(compareOp)).substr(14)) + viewportCase.suffix;
1474
1475					const VkCompareOp ops[DepthTest::QUAD_COUNT] = { compareOp, compareOp, compareOp, compareOp };
1476					depthClipControlTests->addChild(new DepthTest(testCtx, testName, pipelineConstructionType, format, ops,
1477													false, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, false, 0.0f, 1.0f, true, false, true, false, tcu::UVec2(32,32), viewportCase.viewportCase));
1478				}
1479	}
1480	depthTests->addChild(depthClipControlTests.release());
1481#endif // CTS_USES_VULKANSC
1482
1483	return depthTests.release();
1484}
1485
1486} // pipeline
1487} // vkt
1488