• 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 Imagination Technologies Ltd.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Stencil Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktPipelineStencilTests.hpp"
26 #include "vktPipelineClearUtil.hpp"
27 #include "vktPipelineImageUtil.hpp"
28 #include "vktPipelineVertexUtil.hpp"
29 #include "vktPipelineReferenceRenderer.hpp"
30 #include "vktPipelineUniqueRandomIterator.hpp"
31 #include "vktTestCase.hpp"
32 #include "vkImageUtil.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkPrograms.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkRef.hpp"
37 #include "vkRefUtil.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "vkCmdUtil.hpp"
40 #include "vkObjUtil.hpp"
41 #include "tcuImageCompare.hpp"
42 #include "deMemory.h"
43 #include "deRandom.hpp"
44 #include "deStringUtil.hpp"
45 #include "deUniquePtr.hpp"
46 
47 #include <algorithm>
48 #include <sstream>
49 #include <vector>
50 
51 namespace vkt
52 {
53 namespace pipeline
54 {
55 
56 using namespace vk;
57 
58 namespace
59 {
60 
isSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,VkPhysicalDevice device,VkFormat format)61 bool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, VkPhysicalDevice device, VkFormat format)
62 {
63 	VkFormatProperties formatProps;
64 
65 	instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
66 
67 	return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
68 }
69 
70 class StencilOpStateUniqueRandomIterator : public UniqueRandomIterator<VkStencilOpState>
71 {
72 public:
73 								StencilOpStateUniqueRandomIterator	(int seed);
~StencilOpStateUniqueRandomIterator(void)74 	virtual						~StencilOpStateUniqueRandomIterator	(void) {}
75 	virtual VkStencilOpState	getIndexedValue						(deUint32 index);
76 
77 private:
78 
79 	// Pre-calculated constants
80 	const static deUint32		s_stencilOpsLength;
81 	const static deUint32		s_stencilOpsLength2;
82 	const static deUint32		s_stencilOpsLength3;
83 	const static deUint32		s_compareOpsLength;
84 
85 	// Total number of cross-combinations of (stencilFailOp x stencilPassOp x stencilDepthFailOp x stencilCompareOp)
86 	const static deUint32		s_totalStencilOpStates;
87 };
88 
89 
90 class StencilTest : public vkt::TestCase
91 {
92 public:
93 	enum
94 	{
95 		QUAD_COUNT = 4
96 	};
97 
98 	struct StencilStateConfig
99 	{
100 		deUint32	frontReadMask;
101 		deUint32	frontWriteMask;
102 		deUint32	frontRef;
103 
104 		deUint32	backReadMask;
105 		deUint32	backWriteMask;
106 		deUint32	backRef;
107 	};
108 
109 	const static StencilStateConfig			s_stencilStateConfigs[QUAD_COUNT];
110 	const static float						s_quadDepths[QUAD_COUNT];
111 
112 
113 											StencilTest				(tcu::TestContext&			testContext,
114 																	 const std::string&			name,
115 																	 const std::string&			description,
116 																	 VkFormat					stencilFormat,
117 																	 const VkStencilOpState&	stencilOpStateFront,
118 																	 const VkStencilOpState&	stencilOpStateBack,
119 																	 const bool					colorAttachmentEnable,
120 																	 const bool					separateDepthStencilLayouts);
121 	virtual									~StencilTest			(void);
122 	virtual void							initPrograms			(SourceCollections& sourceCollections) const;
123 	virtual void							checkSupport			(Context& context) const;
124 	virtual TestInstance*					createInstance			(Context& context) const;
125 
126 private:
127 	VkFormat								m_stencilFormat;
128 	const VkStencilOpState					m_stencilOpStateFront;
129 	const VkStencilOpState					m_stencilOpStateBack;
130 	const bool								m_colorAttachmentEnable;
131 	const bool								m_separateDepthStencilLayouts;
132 };
133 
134 class StencilTestInstance : public vkt::TestInstance
135 {
136 public:
137 										StencilTestInstance		(Context&					context,
138 																 VkFormat					stencilFormat,
139 																 const VkStencilOpState&	stencilOpStatesFront,
140 																 const VkStencilOpState&	stencilOpStatesBack,
141 																 const bool					colorAttachmentEnable,
142 																 const bool					separateDepthStencilLayouts);
143 	virtual								~StencilTestInstance	(void);
144 	virtual tcu::TestStatus				iterate					(void);
145 
146 private:
147 	tcu::TestStatus						verifyImage				(void);
148 
149 	VkStencilOpState					m_stencilOpStateFront;
150 	VkStencilOpState					m_stencilOpStateBack;
151 	const bool							m_colorAttachmentEnable;
152 	const bool							m_separateDepthStencilLayouts;
153 	const tcu::UVec2					m_renderSize;
154 	const VkFormat						m_colorFormat;
155 	const VkFormat						m_stencilFormat;
156 	VkImageSubresourceRange				m_stencilImageSubresourceRange;
157 
158 	VkImageCreateInfo					m_colorImageCreateInfo;
159 	Move<VkImage>						m_colorImage;
160 	de::MovePtr<Allocation>				m_colorImageAlloc;
161 	Move<VkImage>						m_stencilImage;
162 	de::MovePtr<Allocation>				m_stencilImageAlloc;
163 	Move<VkImageView>					m_colorAttachmentView;
164 	Move<VkImageView>					m_stencilAttachmentView;
165 	Move<VkRenderPass>					m_renderPass;
166 	Move<VkFramebuffer>					m_framebuffer;
167 
168 	Move<VkShaderModule>				m_vertexShaderModule;
169 	Move<VkShaderModule>				m_fragmentShaderModule;
170 
171 	Move<VkBuffer>						m_vertexBuffer;
172 	std::vector<Vertex4RGBA>			m_vertices;
173 	de::MovePtr<Allocation>				m_vertexBufferAlloc;
174 
175 	Move<VkPipelineLayout>				m_pipelineLayout;
176 	Move<VkPipeline>					m_graphicsPipelines[StencilTest::QUAD_COUNT];
177 
178 	Move<VkCommandPool>					m_cmdPool;
179 	Move<VkCommandBuffer>				m_cmdBuffer;
180 };
181 
182 const VkStencilOp stencilOps[] =
183 {
184 	VK_STENCIL_OP_KEEP,
185 	VK_STENCIL_OP_ZERO,
186 	VK_STENCIL_OP_REPLACE,
187 	VK_STENCIL_OP_INCREMENT_AND_CLAMP,
188 	VK_STENCIL_OP_DECREMENT_AND_CLAMP,
189 	VK_STENCIL_OP_INVERT,
190 	VK_STENCIL_OP_INCREMENT_AND_WRAP,
191 	VK_STENCIL_OP_DECREMENT_AND_WRAP
192 };
193 
194 const VkCompareOp compareOps[] =
195 {
196 	VK_COMPARE_OP_NEVER,
197 	VK_COMPARE_OP_LESS,
198 	VK_COMPARE_OP_EQUAL,
199 	VK_COMPARE_OP_LESS_OR_EQUAL,
200 	VK_COMPARE_OP_GREATER,
201 	VK_COMPARE_OP_NOT_EQUAL,
202 	VK_COMPARE_OP_GREATER_OR_EQUAL,
203 	VK_COMPARE_OP_ALWAYS
204 };
205 
206 // StencilOpStateUniqueRandomIterator
207 
208 const deUint32 StencilOpStateUniqueRandomIterator::s_stencilOpsLength		= DE_LENGTH_OF_ARRAY(stencilOps);
209 const deUint32 StencilOpStateUniqueRandomIterator::s_stencilOpsLength2		= s_stencilOpsLength * s_stencilOpsLength;
210 const deUint32 StencilOpStateUniqueRandomIterator::s_stencilOpsLength3		= s_stencilOpsLength2 * s_stencilOpsLength;
211 const deUint32 StencilOpStateUniqueRandomIterator::s_compareOpsLength		= DE_LENGTH_OF_ARRAY(compareOps);
212 const deUint32 StencilOpStateUniqueRandomIterator::s_totalStencilOpStates	= s_stencilOpsLength3 * s_compareOpsLength;
213 
StencilOpStateUniqueRandomIterator(int seed)214 StencilOpStateUniqueRandomIterator::StencilOpStateUniqueRandomIterator (int seed)
215 	: UniqueRandomIterator<VkStencilOpState>(s_totalStencilOpStates, s_totalStencilOpStates, seed)
216 {
217 }
218 
getIndexedValue(deUint32 index)219 VkStencilOpState StencilOpStateUniqueRandomIterator::getIndexedValue (deUint32 index)
220 {
221 	const deUint32 stencilCompareOpIndex = index / s_stencilOpsLength3;
222 	const deUint32 stencilCompareOpSeqIndex = stencilCompareOpIndex * s_stencilOpsLength3;
223 
224 	const deUint32 stencilDepthFailOpIndex = (index - stencilCompareOpSeqIndex) / s_stencilOpsLength2;
225 	const deUint32 stencilDepthFailOpSeqIndex = stencilDepthFailOpIndex * s_stencilOpsLength2;
226 
227 	const deUint32 stencilPassOpIndex = (index - stencilCompareOpSeqIndex - stencilDepthFailOpSeqIndex) / s_stencilOpsLength;
228 	const deUint32 stencilPassOpSeqIndex = stencilPassOpIndex * s_stencilOpsLength;
229 
230 	const deUint32 stencilFailOpIndex = index - stencilCompareOpSeqIndex - stencilDepthFailOpSeqIndex - stencilPassOpSeqIndex;
231 
232 	const VkStencilOpState stencilOpState =
233 	{
234 		stencilOps[stencilFailOpIndex],			// VkStencilOp	failOp;
235 		stencilOps[stencilPassOpIndex],			// VkStencilOp	passOp;
236 		stencilOps[stencilDepthFailOpIndex],	// VkStencilOp	depthFailOp;
237 		compareOps[stencilCompareOpIndex],		// VkCompareOp	compareOp;
238 		0x0,									// deUint32		compareMask;
239 		0x0,									// deUint32		writeMask;
240 		0x0										// deUint32		reference;
241 	};
242 
243 	return stencilOpState;
244 }
245 
246 
247 // StencilTest
248 
249 const StencilTest::StencilStateConfig StencilTest::s_stencilStateConfigs[QUAD_COUNT] =
250 {
251 	//	frontReadMask	frontWriteMask		frontRef		backReadMask	backWriteMask	backRef
252 	{	0xFF,			0xFF,				0xAB,			0xF0,			0xFF,			0xFF	},
253 	{	0xFF,			0xF0,				0xCD,			0xF0,			0xF0,			0xEF	},
254 	{	0xF0,			0x0F,				0xEF,			0xFF,			0x0F,			0xCD	},
255 	{	0xF0,			0x01,				0xFF,			0xFF,			0x01,			0xAB	}
256 };
257 
258 const float StencilTest::s_quadDepths[QUAD_COUNT] =
259 {
260 	0.1f,
261 	0.0f,
262 	0.3f,
263 	0.2f
264 };
265 
StencilTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,VkFormat stencilFormat,const VkStencilOpState & stencilOpStateFront,const VkStencilOpState & stencilOpStateBack,const bool colorAttachmentEnable,const bool separateDepthStencilLayouts)266 StencilTest::StencilTest (tcu::TestContext&			testContext,
267 						  const std::string&		name,
268 						  const std::string&		description,
269 						  VkFormat					stencilFormat,
270 						  const VkStencilOpState&	stencilOpStateFront,
271 						  const VkStencilOpState&	stencilOpStateBack,
272 						  const bool				colorAttachmentEnable,
273 						  const bool				separateDepthStencilLayouts)
274 	: vkt::TestCase					(testContext, name, description)
275 	, m_stencilFormat				(stencilFormat)
276 	, m_stencilOpStateFront			(stencilOpStateFront)
277 	, m_stencilOpStateBack			(stencilOpStateBack)
278 	, m_colorAttachmentEnable		(colorAttachmentEnable)
279 	, m_separateDepthStencilLayouts	(separateDepthStencilLayouts)
280 {
281 }
282 
~StencilTest(void)283 StencilTest::~StencilTest (void)
284 {
285 }
286 
checkSupport(Context & context) const287 void StencilTest::checkSupport (Context& context) const
288 {
289 	if (!isSupportedDepthStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice(), m_stencilFormat))
290 		throw tcu::NotSupportedError(std::string("Unsupported depth/stencil format: ") + getFormatName(m_stencilFormat));
291 
292 	if (m_separateDepthStencilLayouts && !context.isDeviceFunctionalitySupported("VK_KHR_separate_depth_stencil_layouts"))
293 		TCU_THROW(NotSupportedError, "VK_KHR_separate_depth_stencil_layouts is not supported");
294 }
295 
createInstance(Context & context) const296 TestInstance* StencilTest::createInstance (Context& context) const
297 {
298 	return new StencilTestInstance(context, m_stencilFormat, m_stencilOpStateFront, m_stencilOpStateBack, m_colorAttachmentEnable, m_separateDepthStencilLayouts);
299 }
300 
initPrograms(SourceCollections & sourceCollections) const301 void StencilTest::initPrograms (SourceCollections& sourceCollections) const
302 {
303 	if (m_colorAttachmentEnable)
304 	{
305 		sourceCollections.glslSources.add("color_vert") << glu::VertexSource(
306 			"#version 310 es\n"
307 			"layout(location = 0) in vec4 position;\n"
308 			"layout(location = 1) in vec4 color;\n"
309 			"layout(location = 0) out highp vec4 vtxColor;\n"
310 			"void main (void)\n"
311 			"{\n"
312 			"	gl_Position = position;\n"
313 			"	vtxColor = color;\n"
314 			"}\n");
315 
316 		sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(
317 			"#version 310 es\n"
318 			"layout(location = 0) in highp vec4 vtxColor;\n"
319 			"layout(location = 0) out highp vec4 fragColor;\n"
320 			"void main (void)\n"
321 			"{\n"
322 			"	fragColor = vtxColor;\n"
323 			"}\n");
324 	}
325 	else
326 	{
327 		sourceCollections.glslSources.add("color_vert") << glu::VertexSource(
328 			"#version 310 es\n"
329 			"layout(location = 0) in vec4 position;\n"
330 			"layout(location = 1) in vec4 color;\n"
331 			"void main (void)\n"
332 			"{\n"
333 			"	gl_Position = position;\n"
334 			"}\n");
335 
336 		sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(
337 			"#version 310 es\n"
338 			"void main (void)\n"
339 			"{\n"
340 			"}\n");
341 	}
342 }
343 
344 
345 // StencilTestInstance
346 
StencilTestInstance(Context & context,VkFormat stencilFormat,const VkStencilOpState & stencilOpStateFront,const VkStencilOpState & stencilOpStateBack,const bool colorAttachmentEnable,const bool separateDepthStencilLayouts)347 StencilTestInstance::StencilTestInstance (Context&					context,
348 										  VkFormat					stencilFormat,
349 										  const VkStencilOpState&	stencilOpStateFront,
350 										  const VkStencilOpState&	stencilOpStateBack,
351 										  const bool				colorAttachmentEnable,
352 										  const bool				separateDepthStencilLayouts)
353 	: vkt::TestInstance				(context)
354 	, m_stencilOpStateFront			(stencilOpStateFront)
355 	, m_stencilOpStateBack			(stencilOpStateBack)
356 	, m_colorAttachmentEnable		(colorAttachmentEnable)
357 	, m_separateDepthStencilLayouts	(separateDepthStencilLayouts)
358 	, m_renderSize					(32, 32)
359 	, m_colorFormat					(colorAttachmentEnable ? VK_FORMAT_R8G8B8A8_UNORM : VK_FORMAT_UNDEFINED)
360 	, m_stencilFormat				(stencilFormat)
361 {
362 	const DeviceInterface&		vk						= context.getDeviceInterface();
363 	const VkDevice				vkDevice				= context.getDevice();
364 	const deUint32				queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
365 	SimpleAllocator				memAlloc				(vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
366 	const VkComponentMapping	componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
367 
368 	// Create color image
369 	if (m_colorAttachmentEnable)
370 	{
371 		const VkImageCreateInfo colorImageParams =
372 		{
373 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
374 			DE_NULL,																	// const void*				pNext;
375 			0u,																			// VkImageCreateFlags		flags;
376 			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
377 			m_colorFormat,																// VkFormat					format;
378 			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D				extent;
379 			1u,																			// deUint32					mipLevels;
380 			1u,																			// deUint32					arrayLayers;
381 			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
382 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
383 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
384 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
385 			1u,																			// deUint32					queueFamilyIndexCount;
386 			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
387 			VK_IMAGE_LAYOUT_UNDEFINED													// VkImageLayout			initialLayout;
388 		};
389 
390 		m_colorImageCreateInfo	= colorImageParams;
391 		m_colorImage			= createImage(vk, vkDevice, &m_colorImageCreateInfo);
392 
393 		// Allocate and bind color image memory
394 		m_colorImageAlloc		= memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
395 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
396 	}
397 
398 	// Create stencil image
399 	{
400 		const VkImageUsageFlags	usageFlags			= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
401 
402 		const VkImageCreateInfo	stencilImageParams	=
403 		{
404 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType;
405 			DE_NULL,										// const void*				pNext;
406 			0u,												// VkImageCreateFlags		flags;
407 			VK_IMAGE_TYPE_2D,								// VkImageType				imageType;
408 			m_stencilFormat,								// VkFormat					format;
409 			{ m_renderSize.x(), m_renderSize.y(), 1u },		// VkExtent3D				extent;
410 			1u,												// deUint32					mipLevels;
411 			1u,												// deUint32					arrayLayers;
412 			VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits	samples;
413 			VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling;
414 			usageFlags,										// VkImageUsageFlags		usage;
415 			VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode;
416 			1u,												// deUint32					queueFamilyIndexCount;
417 			&queueFamilyIndex,								// const deUint32*			pQueueFamilyIndices;
418 			VK_IMAGE_LAYOUT_UNDEFINED						// VkImageLayout			initialLayout;
419 		};
420 
421 		m_stencilImage = createImage(vk, vkDevice, &stencilImageParams);
422 
423 		// Allocate and bind stencil image memory
424 		m_stencilImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_stencilImage), MemoryRequirement::Any);
425 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_stencilImage, m_stencilImageAlloc->getMemory(), m_stencilImageAlloc->getOffset()));
426 
427 		const VkImageAspectFlags aspect = (mapVkFormat(m_stencilFormat).order == tcu::TextureFormat::DS ? VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT
428 																										: VK_IMAGE_ASPECT_STENCIL_BIT);
429 		m_stencilImageSubresourceRange  = makeImageSubresourceRange(aspect, 0u, stencilImageParams.mipLevels, 0u, stencilImageParams.arrayLayers);
430 	}
431 
432 	// Create color attachment view
433 	if (m_colorAttachmentEnable)
434 	{
435 		const VkImageViewCreateInfo colorAttachmentViewParams =
436 		{
437 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
438 			DE_NULL,											// const void*				pNext;
439 			0u,													// VkImageViewCreateFlags	flags;
440 			*m_colorImage,										// VkImage					image;
441 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
442 			m_colorFormat,										// VkFormat					format;
443 			componentMappingRGBA,								// VkComponentMapping		components;
444 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }		// VkImageSubresourceRange	subresourceRange;
445 		};
446 
447 		m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
448 	}
449 
450 	// Create stencil attachment view
451 	{
452 		const VkImageViewCreateInfo stencilAttachmentViewParams =
453 		{
454 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
455 			DE_NULL,											// const void*				pNext;
456 			0u,													// VkImageViewCreateFlags	flags;
457 			*m_stencilImage,									// VkImage					image;
458 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
459 			m_stencilFormat,									// VkFormat					format;
460 			componentMappingRGBA,								// VkComponentMapping		components;
461 			m_stencilImageSubresourceRange,						// VkImageSubresourceRange	subresourceRange;
462 		};
463 
464 		m_stencilAttachmentView = createImageView(vk, vkDevice, &stencilAttachmentViewParams);
465 	}
466 
467 	// Create render pass
468 	m_renderPass = makeRenderPass(vk, vkDevice, m_colorFormat, m_stencilFormat);
469 
470 	// Create framebuffer
471 	{
472 		std::vector<VkImageView>		attachmentBindInfos;
473 
474 		if (m_colorAttachmentEnable)
475 			attachmentBindInfos.push_back(*m_colorAttachmentView);
476 
477 		attachmentBindInfos.push_back(*m_stencilAttachmentView);
478 
479 		const VkFramebufferCreateInfo	framebufferParams =
480 		{
481 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType			sType;
482 			DE_NULL,											// const void*				pNext;
483 			0u,													// VkFramebufferCreateFlags	flags;
484 			*m_renderPass,										// VkRenderPass				renderPass;
485 			(deUint32)attachmentBindInfos.size(),				// deUint32					attachmentCount;
486 			attachmentBindInfos.data(),							// const VkImageView*		pAttachments;
487 			(deUint32)m_renderSize.x(),							// deUint32					width;
488 			(deUint32)m_renderSize.y(),							// deUint32					height;
489 			1u													// deUint32					layers;
490 		};
491 
492 		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
493 	}
494 
495 	// Create pipeline layout
496 	{
497 		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
498 		{
499 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
500 			DE_NULL,											// const void*					pNext;
501 			0u,													// VkPipelineLayoutCreateFlags	flags;
502 			0u,													// deUint32						setLayoutCount;
503 			DE_NULL,											// const VkDescriptorSetLayout*	pSetLayouts;
504 			0u,													// deUint32						pushConstantRangeCount;
505 			DE_NULL												// const VkPushConstantRange*	pPushConstantRanges;
506 		};
507 
508 		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
509 	}
510 
511 	m_vertexShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
512 	m_fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
513 
514 	// Create pipeline
515 	{
516 		const VkVertexInputBindingDescription vertexInputBindingDescription =
517 		{
518 			0u,										// deUint32					binding;
519 			sizeof(Vertex4RGBA),					// deUint32					strideInBytes;
520 			VK_VERTEX_INPUT_RATE_VERTEX				// VkVertexInputStepRate	inputRate;
521 		};
522 
523 		const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
524 		{
525 			{
526 				0u,									// deUint32	location;
527 				0u,									// deUint32	binding;
528 				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
529 				0u									// deUint32	offsetInBytes;
530 			},
531 			{
532 				1u,									// deUint32	location;
533 				0u,									// deUint32	binding;
534 				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
535 				DE_OFFSET_OF(Vertex4RGBA, color),	// deUint32	offsetInBytes;
536 			}
537 		};
538 
539 		const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
540 		{
541 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
542 			DE_NULL,														// const void*								pNext;
543 			0u,																// VkPipelineVertexInputStateCreateFlags	flags;
544 			1u,																// deUint32									vertexBindingDescriptionCount;
545 			&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
546 			2u,																// deUint32									vertexAttributeDescriptionCount;
547 			vertexInputAttributeDescriptions								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
548 		};
549 
550 		const std::vector<VkViewport>	viewports	(1, makeViewport(m_renderSize));
551 		const std::vector<VkRect2D>		scissors	(1, makeRect2D(m_renderSize));
552 
553 		const bool isDepthEnabled = (vk::mapVkFormat(m_stencilFormat).order != tcu::TextureFormat::S);
554 
555 		VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
556 		{
557 			VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
558 			DE_NULL,													// const void*								pNext;
559 			0u,															// VkPipelineDepthStencilStateCreateFlags	flags;
560 			isDepthEnabled,												// VkBool32									depthTestEnable;
561 			isDepthEnabled,												// VkBool32									depthWriteEnable;
562 			VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
563 			false,														// VkBool32									depthBoundsTestEnable;
564 			true,														// VkBool32									stencilTestEnable;
565 			m_stencilOpStateFront,										// VkStencilOpState							front;
566 			m_stencilOpStateBack,										// VkStencilOpState							back;
567 			0.0f,														// float									minDepthBounds;
568 			1.0f														// float									maxDepthBounds;
569 		};
570 
571 		// Setup different stencil masks and refs in each quad
572 		for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
573 		{
574 			const StencilTest::StencilStateConfig&	config	= StencilTest::s_stencilStateConfigs[quadNdx];
575 			VkStencilOpState&						front	= depthStencilStateParams.front;
576 			VkStencilOpState&						back	= depthStencilStateParams.back;
577 
578 			front.compareMask	= config.frontReadMask;
579 			front.writeMask		= config.frontWriteMask;
580 			front.reference		= config.frontRef;
581 
582 			back.compareMask	= config.backReadMask;
583 			back.writeMask		= config.backWriteMask;
584 			back.reference		= config.backRef;
585 
586 			m_graphicsPipelines[quadNdx] = makeGraphicsPipeline(vk,										// const DeviceInterface&                        vk
587 																vkDevice,								// const VkDevice                                device
588 																*m_pipelineLayout,						// const VkPipelineLayout                        pipelineLayout
589 																*m_vertexShaderModule,					// const VkShaderModule                          vertexShaderModule
590 																DE_NULL,								// const VkShaderModule                          tessellationControlModule
591 																DE_NULL,								// const VkShaderModule                          tessellationEvalModule
592 																DE_NULL,								// const VkShaderModule                          geometryShaderModule
593 																*m_fragmentShaderModule,				// const VkShaderModule                          fragmentShaderModule
594 																*m_renderPass,							// const VkRenderPass                            renderPass
595 																viewports,								// const std::vector<VkViewport>&                viewports
596 																scissors,								// const std::vector<VkRect2D>&                  scissors
597 																VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology                     topology
598 																0u,										// const deUint32                                subpass
599 																0u,										// const deUint32                                patchControlPoints
600 																&vertexInputStateParams,				// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
601 																DE_NULL,								// const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
602 																DE_NULL,								// const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
603 																&depthStencilStateParams);				// const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
604 		}
605 	}
606 
607 
608 	// Create vertex buffer
609 	{
610 		const VkBufferCreateInfo vertexBufferParams =
611 		{
612 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
613 			DE_NULL,									// const void*			pNext;
614 			0u,											// VkBufferCreateFlags	flags;
615 			1024u,										// VkDeviceSize			size;
616 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
617 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
618 			1u,											// deUint32				queueFamilyIndexCount;
619 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
620 		};
621 
622 		m_vertices			= createOverlappingQuads();
623 		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
624 		m_vertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
625 
626 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
627 
628 		// Adjust depths
629 		for (int quadNdx = 0; quadNdx < 4; quadNdx++)
630 			for (int vertexNdx = 0; vertexNdx < 6; vertexNdx++)
631 				m_vertices[quadNdx * 6 + vertexNdx].position.z() = StencilTest::s_quadDepths[quadNdx];
632 
633 		// Load vertices into vertex buffer
634 		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
635 		flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
636 	}
637 
638 	// Create command pool
639 	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
640 
641 	// Create command buffer
642 	{
643 		const VkImageMemoryBarrier	colorImageBarrier					=
644 		{
645 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType            sType;
646 			DE_NULL,										// const void*                pNext;
647 			(VkAccessFlags)0,								// VkAccessFlags              srcAccessMask;
648 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags              dstAccessMask;
649 			VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout              oldLayout;
650 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout              newLayout;
651 			VK_QUEUE_FAMILY_IGNORED,						// uint32_t                   srcQueueFamilyIndex;
652 			VK_QUEUE_FAMILY_IGNORED,						// uint32_t                   dstQueueFamilyIndex;
653 			*m_colorImage,									// VkImage                    image;
654 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }	// VkImageSubresourceRange    subresourceRange;
655 		};
656 
657 		VkImageSubresourceRange		stencilImageBarrierSubresourceRange	= m_stencilImageSubresourceRange;
658 		VkImageLayout				newLayout							= VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
659 		if (m_separateDepthStencilLayouts)
660 		{
661 			stencilImageBarrierSubresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
662 			newLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR;
663 		}
664 
665 		const VkImageMemoryBarrier	stencilImageBarrier					=
666 		{
667 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,									// VkStructureType            sType;
668 			DE_NULL,																// const void*                pNext;
669 			(VkAccessFlags)0,														// VkAccessFlags              srcAccessMask;
670 			VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,							// VkAccessFlags              dstAccessMask;
671 			VK_IMAGE_LAYOUT_UNDEFINED,												// VkImageLayout              oldLayout;
672 			newLayout,																// VkImageLayout              newLayout;
673 			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   srcQueueFamilyIndex;
674 			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   dstQueueFamilyIndex;
675 			*m_stencilImage,														// VkImage                    image;
676 			stencilImageBarrierSubresourceRange,									// VkImageSubresourceRange    subresourceRange;
677 		};
678 
679 		std::vector<VkClearValue>			attachmentClearValues;
680 		std::vector<VkImageMemoryBarrier>	imageLayoutBarriers;
681 
682 		if (m_colorAttachmentEnable)
683 		{
684 			attachmentClearValues.push_back(defaultClearValue(m_colorFormat));
685 			imageLayoutBarriers.push_back(colorImageBarrier);
686 		}
687 
688 		attachmentClearValues.push_back(defaultClearValue(m_stencilFormat));
689 		imageLayoutBarriers.push_back(stencilImageBarrier);
690 
691 		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
692 
693 		beginCommandBuffer(vk, *m_cmdBuffer, 0u);
694 
695 		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, (VkDependencyFlags)0,
696 			0u, DE_NULL, 0u, DE_NULL, (deUint32)imageLayoutBarriers.size(), imageLayoutBarriers.data());
697 
698 		beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), (deUint32)attachmentClearValues.size(), attachmentClearValues.data());
699 
700 		const VkDeviceSize		quadOffset		= (m_vertices.size() / StencilTest::QUAD_COUNT) * sizeof(Vertex4RGBA);
701 
702 		for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
703 		{
704 			VkDeviceSize vertexBufferOffset = quadOffset * quadNdx;
705 
706 			vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelines[quadNdx]);
707 			vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
708 			vk.cmdDraw(*m_cmdBuffer, (deUint32)(m_vertices.size() / StencilTest::QUAD_COUNT), 1, 0, 0);
709 		}
710 
711 		endRenderPass(vk, *m_cmdBuffer);
712 		endCommandBuffer(vk, *m_cmdBuffer);
713 	}
714 }
715 
~StencilTestInstance(void)716 StencilTestInstance::~StencilTestInstance (void)
717 {
718 }
719 
iterate(void)720 tcu::TestStatus StencilTestInstance::iterate (void)
721 {
722 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
723 	const VkDevice				vkDevice	= m_context.getDevice();
724 	const VkQueue				queue		= m_context.getUniversalQueue();
725 
726 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
727 
728 	return verifyImage();
729 }
730 
verifyImage(void)731 tcu::TestStatus StencilTestInstance::verifyImage (void)
732 {
733 	const tcu::TextureFormat	tcuColorFormat		= mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM);
734 	const tcu::TextureFormat	tcuStencilFormat	= mapVkFormat(m_stencilFormat);
735 	const ColorVertexShader		vertexShader;
736 	const ColorFragmentShader	fragmentShader		(tcuColorFormat, tcuStencilFormat);
737 	const rr::Program			program				(&vertexShader, &fragmentShader);
738 	ReferenceRenderer			refRenderer			(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuStencilFormat, &program);
739 	bool						colorCompareOk		= false;
740 	bool						stencilCompareOk	= false;
741 
742 	// Render reference image
743 	{
744 		// Set depth state
745 		rr::RenderState renderState(refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits);
746 
747 		renderState.fragOps.depthTestEnabled	= true;
748 		renderState.fragOps.depthFunc			= mapVkCompareOp(VK_COMPARE_OP_LESS);
749 		renderState.fragOps.stencilTestEnabled	= true;
750 
751 		rr::StencilState& refStencilFront	= renderState.fragOps.stencilStates[rr::FACETYPE_FRONT];
752 		rr::StencilState& refStencilBack	= renderState.fragOps.stencilStates[rr::FACETYPE_BACK];
753 
754 		refStencilFront.sFail		= mapVkStencilOp(m_stencilOpStateFront.failOp);
755 		refStencilFront.dpFail		= mapVkStencilOp(m_stencilOpStateFront.depthFailOp);
756 		refStencilFront.dpPass		= mapVkStencilOp(m_stencilOpStateFront.passOp);
757 		refStencilFront.func		= mapVkCompareOp(m_stencilOpStateFront.compareOp);
758 
759 		refStencilBack.sFail		= mapVkStencilOp(m_stencilOpStateBack.failOp);
760 		refStencilBack.dpPass		= mapVkStencilOp(m_stencilOpStateBack.passOp);
761 		refStencilBack.dpFail		= mapVkStencilOp(m_stencilOpStateBack.depthFailOp);
762 		refStencilBack.func			= mapVkCompareOp(m_stencilOpStateBack.compareOp);
763 
764 		// Reverse winding of vertices, as Vulkan screen coordinates start at upper left
765 		std::vector<Vertex4RGBA> cwVertices(m_vertices);
766 		for (size_t vertexNdx = 0; vertexNdx < cwVertices.size() - 2; vertexNdx += 3)
767 		{
768 			const Vertex4RGBA cwVertex1	= cwVertices[vertexNdx + 1];
769 
770 			cwVertices[vertexNdx + 1]	= cwVertices[vertexNdx + 2];
771 			cwVertices[vertexNdx + 2]	= cwVertex1;
772 		}
773 
774 		for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
775 		{
776 			refStencilFront.ref			= (int)StencilTest::s_stencilStateConfigs[quadNdx].frontRef;
777 			refStencilFront.compMask	= StencilTest::s_stencilStateConfigs[quadNdx].frontReadMask;
778 			refStencilFront.writeMask	= StencilTest::s_stencilStateConfigs[quadNdx].frontWriteMask;
779 
780 			refStencilBack.ref			= (int)StencilTest::s_stencilStateConfigs[quadNdx].backRef;
781 			refStencilBack.compMask		= StencilTest::s_stencilStateConfigs[quadNdx].backReadMask;
782 			refStencilBack.writeMask	= StencilTest::s_stencilStateConfigs[quadNdx].backWriteMask;
783 
784 			refRenderer.draw(renderState,
785 							 rr::PRIMITIVETYPE_TRIANGLES,
786 							 std::vector<Vertex4RGBA>(cwVertices.begin() + quadNdx * 6,
787 													  cwVertices.begin() + (quadNdx + 1) * 6));
788 		}
789 	}
790 
791 	// Compare result with reference image
792 	if (m_colorAttachmentEnable)
793 	{
794 		const DeviceInterface&				vk					= m_context.getDeviceInterface();
795 		const VkDevice						vkDevice			= m_context.getDevice();
796 		const VkQueue						queue				= m_context.getUniversalQueue();
797 		const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
798 		SimpleAllocator						allocator			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
799 		de::UniquePtr<tcu::TextureLevel>	result				(readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize).release());
800 
801 		colorCompareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
802 																   "IntImageCompare",
803 																   "Image comparison",
804 																   refRenderer.getAccess(),
805 																   result->getAccess(),
806 																   tcu::UVec4(2, 2, 2, 2),
807 																   tcu::IVec3(1, 1, 0),
808 																   true,
809 																   tcu::COMPARE_LOG_RESULT);
810 	}
811 	else
812 	{
813 		colorCompareOk = true;
814 	}
815 
816 	// Compare stencil result with reference image
817 	{
818 		const DeviceInterface&				vk					= m_context.getDeviceInterface();
819 		const VkDevice						vkDevice			= m_context.getDevice();
820 		const VkQueue						queue				= m_context.getUniversalQueue();
821 		const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
822 		SimpleAllocator						allocator			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
823 		de::UniquePtr<tcu::TextureLevel>	result				(readStencilAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_stencilImage, m_stencilFormat, m_renderSize).release());
824 
825 		{
826 			const tcu::PixelBufferAccess stencilAccess (tcu::getEffectiveDepthStencilAccess(refRenderer.getDepthStencilAccess(), tcu::Sampler::MODE_STENCIL));
827 			stencilCompareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
828 																		 "StencilImageCompare",
829 																		 "Stencil image comparison",
830 																		 stencilAccess,
831 																		 result->getAccess(),
832 																		 tcu::UVec4(2, 2, 2, 2),
833 																		 tcu::IVec3(1, 1, 0),
834 																		 true,
835 																		 tcu::COMPARE_LOG_RESULT);
836 		}
837 	}
838 
839 	if (colorCompareOk && stencilCompareOk)
840 		return tcu::TestStatus::pass("Result image matches reference");
841 	else
842 		return tcu::TestStatus::fail("Image mismatch");
843 }
844 
845 
846 // Utilities for test names
847 
getShortName(VkStencilOp stencilOp)848 const char* getShortName (VkStencilOp stencilOp)
849 {
850 	switch (stencilOp)
851 	{
852 		case VK_STENCIL_OP_KEEP:					return "keep";
853 		case VK_STENCIL_OP_ZERO:					return "zero";
854 		case VK_STENCIL_OP_REPLACE:					return "repl";
855 		case VK_STENCIL_OP_INCREMENT_AND_CLAMP:		return "incc";
856 		case VK_STENCIL_OP_DECREMENT_AND_CLAMP:		return "decc";
857 		case VK_STENCIL_OP_INVERT:					return "inv";
858 		case VK_STENCIL_OP_INCREMENT_AND_WRAP:		return "wrap";
859 		case VK_STENCIL_OP_DECREMENT_AND_WRAP:		return "decw";
860 
861 		default:
862 			DE_FATAL("Invalid VkStencilOpState value");
863 	}
864 	return DE_NULL;
865 }
866 
getStencilStateSetDescription(const VkStencilOpState & stencilOpStateFront,const VkStencilOpState & stencilOpStateBack)867 std::string getStencilStateSetDescription(const VkStencilOpState& stencilOpStateFront,
868 										  const VkStencilOpState& stencilOpStateBack)
869 {
870 	std::ostringstream desc;
871 
872 	desc << "\nFront faces:\n" << stencilOpStateFront;
873 	desc << "Back faces:\n" << stencilOpStateBack;
874 
875 	return desc.str();
876 }
877 
getFormatCaseName(VkFormat format)878 std::string getFormatCaseName (VkFormat format)
879 {
880 	const std::string fullName = getFormatName(format);
881 
882 	DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
883 
884 	return de::toLower(fullName.substr(10));
885 }
886 
887 } // anonymous
888 
createStencilTests(tcu::TestContext & testCtx)889 tcu::TestCaseGroup* createStencilTests (tcu::TestContext& testCtx)
890 {
891 	const VkFormat stencilFormats[] =
892 	{
893 		VK_FORMAT_S8_UINT,
894 		VK_FORMAT_D16_UNORM_S8_UINT,
895 		VK_FORMAT_D24_UNORM_S8_UINT,
896 		VK_FORMAT_D32_SFLOAT_S8_UINT
897 	};
898 
899 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(compareOps) == 8);
900 	DE_STATIC_ASSERT(vk::VK_COMPARE_OP_LAST == 8);
901 
902 	static const char* compareOpNames[8] =
903 	{
904 		"comp_never",
905 		"comp_less",
906 		"comp_equal",
907 		"comp_less_or_equal",
908 		"comp_greater",
909 		"comp_not_equal",
910 		"comp_greater_or_equal",
911 		"comp_always"
912 	};
913 
914 	de::MovePtr<tcu::TestCaseGroup>		stencilTests				(new tcu::TestCaseGroup(testCtx, "stencil", "Stencil tests"));
915 	de::MovePtr<tcu::TestCaseGroup>		noColorAttachmentTests		(new tcu::TestCaseGroup(testCtx, "nocolor", "Stencil tests with no color attachment"));
916 	const bool							colorAttachmentEnabled[]	= { true, false };
917 
918 	for (deUint32 colorAttachmentEnabledIdx = 0; colorAttachmentEnabledIdx < DE_LENGTH_OF_ARRAY(colorAttachmentEnabled); colorAttachmentEnabledIdx++)
919 	{
920 		const bool							colorEnabled				= colorAttachmentEnabled[colorAttachmentEnabledIdx];
921 		de::MovePtr<tcu::TestCaseGroup>		formatTests					(new tcu::TestCaseGroup(testCtx, "format", "Uses different stencil formats"));
922 		StencilOpStateUniqueRandomIterator	stencilOpItr				(123);
923 
924 		for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(stencilFormats); formatNdx++)
925 		{
926 			const VkFormat	stencilFormat				= stencilFormats[formatNdx];
927 			const bool		hasDepth					= tcu::hasDepthComponent(mapVkFormat(stencilFormat).order);
928 			const bool		hasStencil					= tcu::hasStencilComponent(mapVkFormat(stencilFormat).order);
929 			const int		separateLayoutsLoopCount	= (hasDepth && hasStencil) ? 2 : 1;
930 
931 			for (int separateDepthStencilLayouts = 0; separateDepthStencilLayouts < separateLayoutsLoopCount; ++separateDepthStencilLayouts)
932 			{
933 				const bool			useSeparateDepthStencilLayouts	= bool(separateDepthStencilLayouts);
934 
935 				de::MovePtr<tcu::TestCaseGroup>	formatTest		(new tcu::TestCaseGroup(testCtx,
936 																						(getFormatCaseName(stencilFormat) + ((useSeparateDepthStencilLayouts) ? "_separate_layouts" : "")).c_str(),
937 																						(std::string("Uses format ") + getFormatName(stencilFormat) + ((useSeparateDepthStencilLayouts) ? " with separate depth/stencil layouts" : "")).c_str()));
938 
939 				de::MovePtr<tcu::TestCaseGroup>	stencilStateTests;
940 				{
941 					std::ostringstream desc;
942 					desc << "Draws 4 quads with the following depths and dynamic stencil states: ";
943 
944 					for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
945 					{
946 						const StencilTest::StencilStateConfig& stencilConfig = StencilTest::s_stencilStateConfigs[quadNdx];
947 
948 						desc << "(" << quadNdx << ") "
949 							 << "z = " << StencilTest::s_quadDepths[quadNdx] << ", "
950 							 << "frontReadMask = " << stencilConfig.frontReadMask << ", "
951 							 << "frontWriteMask = " << stencilConfig.frontWriteMask << ", "
952 							 << "frontRef = " << stencilConfig.frontRef << ", "
953 							 << "backReadMask = " << stencilConfig.backReadMask << ", "
954 							 << "backWriteMask = " << stencilConfig.backWriteMask << ", "
955 							 << "backRef = " << stencilConfig.backRef;
956 					}
957 
958 					stencilStateTests = de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, "states", desc.str().c_str()));
959 				}
960 
961 				stencilOpItr.reset();
962 
963 				for (deUint32 failOpNdx = 0u; failOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); failOpNdx++)
964 				{
965 					const std::string				failOpName	= std::string("fail_") + getShortName(stencilOps[failOpNdx]);
966 					de::MovePtr<tcu::TestCaseGroup>	failOpTest	(new tcu::TestCaseGroup(testCtx, failOpName.c_str(), ""));
967 
968 					for (deUint32 passOpNdx = 0u; passOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); passOpNdx++)
969 					{
970 						const std::string				passOpName	= std::string("pass_") + getShortName(stencilOps[passOpNdx]);
971 						de::MovePtr<tcu::TestCaseGroup>	passOpTest	(new tcu::TestCaseGroup(testCtx, passOpName.c_str(), ""));
972 
973 						for (deUint32 dFailOpNdx = 0u; dFailOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); dFailOpNdx++)
974 						{
975 							const std::string				dFailOpName	= std::string("dfail_") + getShortName(stencilOps[dFailOpNdx]);
976 							de::MovePtr<tcu::TestCaseGroup>	dFailOpTest	(new tcu::TestCaseGroup(testCtx, dFailOpName.c_str(), ""));
977 
978 							for (deUint32 compareOpNdx = 0u; compareOpNdx < DE_LENGTH_OF_ARRAY(compareOps); compareOpNdx++)
979 							{
980 								// Iterate front set of stencil state in ascending order
981 								const VkStencilOpState	stencilStateFront	=
982 								{
983 									stencilOps[failOpNdx],		// failOp
984 									stencilOps[passOpNdx],		// passOp
985 									stencilOps[dFailOpNdx],		// depthFailOp
986 									compareOps[compareOpNdx],	// compareOp
987 									0x0,						// compareMask
988 									0x0,						// writeMask
989 									0x0							// reference
990 								};
991 
992 								// Iterate back set of stencil state in random order
993 								const VkStencilOpState	stencilStateBack	= stencilOpItr.next();
994 								const std::string		caseName			= compareOpNames[compareOpNdx];
995 								const std::string		caseDesc			= getStencilStateSetDescription(stencilStateFront, stencilStateBack);
996 
997 								dFailOpTest->addChild(new StencilTest(testCtx, caseName, caseDesc, stencilFormat, stencilStateFront, stencilStateBack, colorEnabled, useSeparateDepthStencilLayouts));
998 							}
999 							passOpTest->addChild(dFailOpTest.release());
1000 						}
1001 						failOpTest->addChild(passOpTest.release());
1002 					}
1003 					stencilStateTests->addChild(failOpTest.release());
1004 				}
1005 
1006 				formatTest->addChild(stencilStateTests.release());
1007 				formatTests->addChild(formatTest.release());
1008 			}
1009 		}
1010 
1011 		if (colorEnabled)
1012 			stencilTests->addChild(formatTests.release());
1013 		else
1014 			noColorAttachmentTests->addChild(formatTests.release());
1015 	}
1016 
1017 	stencilTests->addChild(noColorAttachmentTests.release());
1018 
1019 	return stencilTests.release();
1020 }
1021 
1022 } // pipeline
1023 } // vkt
1024