• 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 	if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") && !context.getPortabilitySubsetFeatures().separateStencilMaskRef)
296 		TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Separate stencil mask references are not supported by this implementation");
297 }
298 
createInstance(Context & context) const299 TestInstance* StencilTest::createInstance (Context& context) const
300 {
301 	return new StencilTestInstance(context, m_stencilFormat, m_stencilOpStateFront, m_stencilOpStateBack, m_colorAttachmentEnable, m_separateDepthStencilLayouts);
302 }
303 
initPrograms(SourceCollections & sourceCollections) const304 void StencilTest::initPrograms (SourceCollections& sourceCollections) const
305 {
306 	if (m_colorAttachmentEnable)
307 	{
308 		sourceCollections.glslSources.add("color_vert") << glu::VertexSource(
309 			"#version 310 es\n"
310 			"layout(location = 0) in vec4 position;\n"
311 			"layout(location = 1) in vec4 color;\n"
312 			"layout(location = 0) out highp vec4 vtxColor;\n"
313 			"void main (void)\n"
314 			"{\n"
315 			"	gl_Position = position;\n"
316 			"	vtxColor = color;\n"
317 			"}\n");
318 
319 		sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(
320 			"#version 310 es\n"
321 			"layout(location = 0) in highp vec4 vtxColor;\n"
322 			"layout(location = 0) out highp vec4 fragColor;\n"
323 			"void main (void)\n"
324 			"{\n"
325 			"	fragColor = vtxColor;\n"
326 			"}\n");
327 	}
328 	else
329 	{
330 		sourceCollections.glslSources.add("color_vert") << glu::VertexSource(
331 			"#version 310 es\n"
332 			"layout(location = 0) in vec4 position;\n"
333 			"layout(location = 1) in vec4 color;\n"
334 			"void main (void)\n"
335 			"{\n"
336 			"	gl_Position = position;\n"
337 			"}\n");
338 	}
339 }
340 
341 
342 // StencilTestInstance
343 
StencilTestInstance(Context & context,VkFormat stencilFormat,const VkStencilOpState & stencilOpStateFront,const VkStencilOpState & stencilOpStateBack,const bool colorAttachmentEnable,const bool separateDepthStencilLayouts)344 StencilTestInstance::StencilTestInstance (Context&					context,
345 										  VkFormat					stencilFormat,
346 										  const VkStencilOpState&	stencilOpStateFront,
347 										  const VkStencilOpState&	stencilOpStateBack,
348 										  const bool				colorAttachmentEnable,
349 										  const bool				separateDepthStencilLayouts)
350 	: vkt::TestInstance				(context)
351 	, m_stencilOpStateFront			(stencilOpStateFront)
352 	, m_stencilOpStateBack			(stencilOpStateBack)
353 	, m_colorAttachmentEnable		(colorAttachmentEnable)
354 	, m_separateDepthStencilLayouts	(separateDepthStencilLayouts)
355 	, m_renderSize					(32, 32)
356 	, m_colorFormat					(colorAttachmentEnable ? VK_FORMAT_R8G8B8A8_UNORM : VK_FORMAT_UNDEFINED)
357 	, m_stencilFormat				(stencilFormat)
358 {
359 	const DeviceInterface&		vk						= context.getDeviceInterface();
360 	const VkDevice				vkDevice				= context.getDevice();
361 	const deUint32				queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
362 	SimpleAllocator				memAlloc				(vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
363 	const VkComponentMapping	componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
364 
365 	// Create color image
366 	if (m_colorAttachmentEnable)
367 	{
368 		const VkImageCreateInfo colorImageParams =
369 		{
370 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
371 			DE_NULL,																	// const void*				pNext;
372 			0u,																			// VkImageCreateFlags		flags;
373 			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
374 			m_colorFormat,																// VkFormat					format;
375 			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D				extent;
376 			1u,																			// deUint32					mipLevels;
377 			1u,																			// deUint32					arrayLayers;
378 			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
379 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
380 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
381 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
382 			1u,																			// deUint32					queueFamilyIndexCount;
383 			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
384 			VK_IMAGE_LAYOUT_UNDEFINED													// VkImageLayout			initialLayout;
385 		};
386 
387 		m_colorImageCreateInfo	= colorImageParams;
388 		m_colorImage			= createImage(vk, vkDevice, &m_colorImageCreateInfo);
389 
390 		// Allocate and bind color image memory
391 		m_colorImageAlloc		= memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
392 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
393 	}
394 
395 	// Create stencil image
396 	{
397 		const VkImageUsageFlags	usageFlags			= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
398 
399 		const VkImageCreateInfo	stencilImageParams	=
400 		{
401 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType;
402 			DE_NULL,										// const void*				pNext;
403 			0u,												// VkImageCreateFlags		flags;
404 			VK_IMAGE_TYPE_2D,								// VkImageType				imageType;
405 			m_stencilFormat,								// VkFormat					format;
406 			{ m_renderSize.x(), m_renderSize.y(), 1u },		// VkExtent3D				extent;
407 			1u,												// deUint32					mipLevels;
408 			1u,												// deUint32					arrayLayers;
409 			VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits	samples;
410 			VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling;
411 			usageFlags,										// VkImageUsageFlags		usage;
412 			VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode;
413 			1u,												// deUint32					queueFamilyIndexCount;
414 			&queueFamilyIndex,								// const deUint32*			pQueueFamilyIndices;
415 			VK_IMAGE_LAYOUT_UNDEFINED						// VkImageLayout			initialLayout;
416 		};
417 
418 		m_stencilImage = createImage(vk, vkDevice, &stencilImageParams);
419 
420 		// Allocate and bind stencil image memory
421 		m_stencilImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_stencilImage), MemoryRequirement::Any);
422 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_stencilImage, m_stencilImageAlloc->getMemory(), m_stencilImageAlloc->getOffset()));
423 
424 		const VkImageAspectFlags aspect = (mapVkFormat(m_stencilFormat).order == tcu::TextureFormat::DS ? VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT
425 																										: VK_IMAGE_ASPECT_STENCIL_BIT);
426 		m_stencilImageSubresourceRange  = makeImageSubresourceRange(aspect, 0u, stencilImageParams.mipLevels, 0u, stencilImageParams.arrayLayers);
427 	}
428 
429 	// Create color attachment view
430 	if (m_colorAttachmentEnable)
431 	{
432 		const VkImageViewCreateInfo colorAttachmentViewParams =
433 		{
434 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
435 			DE_NULL,											// const void*				pNext;
436 			0u,													// VkImageViewCreateFlags	flags;
437 			*m_colorImage,										// VkImage					image;
438 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
439 			m_colorFormat,										// VkFormat					format;
440 			componentMappingRGBA,								// VkComponentMapping		components;
441 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }		// VkImageSubresourceRange	subresourceRange;
442 		};
443 
444 		m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
445 	}
446 
447 	// Create stencil attachment view
448 	{
449 		const VkImageViewCreateInfo stencilAttachmentViewParams =
450 		{
451 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
452 			DE_NULL,											// const void*				pNext;
453 			0u,													// VkImageViewCreateFlags	flags;
454 			*m_stencilImage,									// VkImage					image;
455 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
456 			m_stencilFormat,									// VkFormat					format;
457 			componentMappingRGBA,								// VkComponentMapping		components;
458 			m_stencilImageSubresourceRange,						// VkImageSubresourceRange	subresourceRange;
459 		};
460 
461 		m_stencilAttachmentView = createImageView(vk, vkDevice, &stencilAttachmentViewParams);
462 	}
463 
464 	// Create render pass
465 	m_renderPass = makeRenderPass(vk, vkDevice, m_colorFormat, m_stencilFormat);
466 
467 	// Create framebuffer
468 	{
469 		std::vector<VkImageView>		attachmentBindInfos;
470 
471 		if (m_colorAttachmentEnable)
472 			attachmentBindInfos.push_back(*m_colorAttachmentView);
473 
474 		attachmentBindInfos.push_back(*m_stencilAttachmentView);
475 
476 		const VkFramebufferCreateInfo	framebufferParams =
477 		{
478 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType			sType;
479 			DE_NULL,											// const void*				pNext;
480 			0u,													// VkFramebufferCreateFlags	flags;
481 			*m_renderPass,										// VkRenderPass				renderPass;
482 			(deUint32)attachmentBindInfos.size(),				// deUint32					attachmentCount;
483 			attachmentBindInfos.data(),							// const VkImageView*		pAttachments;
484 			(deUint32)m_renderSize.x(),							// deUint32					width;
485 			(deUint32)m_renderSize.y(),							// deUint32					height;
486 			1u													// deUint32					layers;
487 		};
488 
489 		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
490 	}
491 
492 	// Create pipeline layout
493 	{
494 		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
495 		{
496 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
497 			DE_NULL,											// const void*					pNext;
498 			0u,													// VkPipelineLayoutCreateFlags	flags;
499 			0u,													// deUint32						setLayoutCount;
500 			DE_NULL,											// const VkDescriptorSetLayout*	pSetLayouts;
501 			0u,													// deUint32						pushConstantRangeCount;
502 			DE_NULL												// const VkPushConstantRange*	pPushConstantRanges;
503 		};
504 
505 		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
506 	}
507 
508 	m_vertexShaderModule		= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
509 	if (m_colorAttachmentEnable)
510 		m_fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
511 
512 	// Create pipeline
513 	{
514 		const VkVertexInputBindingDescription vertexInputBindingDescription =
515 		{
516 			0u,										// deUint32					binding;
517 			sizeof(Vertex4RGBA),					// deUint32					strideInBytes;
518 			VK_VERTEX_INPUT_RATE_VERTEX				// VkVertexInputStepRate	inputRate;
519 		};
520 
521 		const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
522 		{
523 			{
524 				0u,									// deUint32	location;
525 				0u,									// deUint32	binding;
526 				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
527 				0u									// deUint32	offsetInBytes;
528 			},
529 			{
530 				1u,									// deUint32	location;
531 				0u,									// deUint32	binding;
532 				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
533 				DE_OFFSET_OF(Vertex4RGBA, color),	// deUint32	offsetInBytes;
534 			}
535 		};
536 
537 		const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
538 		{
539 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
540 			DE_NULL,														// const void*								pNext;
541 			0u,																// VkPipelineVertexInputStateCreateFlags	flags;
542 			1u,																// deUint32									vertexBindingDescriptionCount;
543 			&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
544 			2u,																// deUint32									vertexAttributeDescriptionCount;
545 			vertexInputAttributeDescriptions								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
546 		};
547 
548 		const std::vector<VkViewport>	viewports	(1, makeViewport(m_renderSize));
549 		const std::vector<VkRect2D>		scissors	(1, makeRect2D(m_renderSize));
550 
551 		const bool isDepthEnabled = (vk::mapVkFormat(m_stencilFormat).order != tcu::TextureFormat::S);
552 
553 		VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
554 		{
555 			VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
556 			DE_NULL,													// const void*								pNext;
557 			0u,															// VkPipelineDepthStencilStateCreateFlags	flags;
558 			isDepthEnabled,												// VkBool32									depthTestEnable;
559 			isDepthEnabled,												// VkBool32									depthWriteEnable;
560 			VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
561 			false,														// VkBool32									depthBoundsTestEnable;
562 			true,														// VkBool32									stencilTestEnable;
563 			m_stencilOpStateFront,										// VkStencilOpState							front;
564 			m_stencilOpStateBack,										// VkStencilOpState							back;
565 			0.0f,														// float									minDepthBounds;
566 			1.0f														// float									maxDepthBounds;
567 		};
568 
569 		// Make sure rasterization is not disabled when the fragment shader is missing.
570 		const vk::VkPipelineRasterizationStateCreateInfo rasterizationStateParams =
571 		{
572 			vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	//	VkStructureType							sType;
573 			nullptr,														//	const void*								pNext;
574 			0u,																//	VkPipelineRasterizationStateCreateFlags	flags;
575 			VK_FALSE,														//	VkBool32								depthClampEnable;
576 			VK_FALSE,														//	VkBool32								rasterizerDiscardEnable;
577 			vk::VK_POLYGON_MODE_FILL,										//	VkPolygonMode							polygonMode;
578 			vk::VK_CULL_MODE_NONE,											//	VkCullModeFlags							cullMode;
579 			vk::VK_FRONT_FACE_COUNTER_CLOCKWISE,							//	VkFrontFace								frontFace;
580 			VK_FALSE,														//	VkBool32								depthBiasEnable;
581 			0.0f,															//	float									depthBiasConstantFactor;
582 			0.0f,															//	float									depthBiasClamp;
583 			0.0f,															//	float									depthBiasSlopeFactor;
584 			1.0f,															//	float									lineWidth;
585 		};
586 
587 		const vk::VkPipelineColorBlendStateCreateInfo colorBlendStateParams
588 		{
589 			vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType
590 			DE_NULL,														// const void*									pNext
591 			0u,																// VkPipelineColorBlendStateCreateFlags			flags
592 			VK_FALSE,														// VkBool32										logicOpEnable
593 			vk::VK_LOGIC_OP_CLEAR,											// VkLogicOp									logicOp
594 			0u,																// deUint32										attachmentCount
595 			DE_NULL,														// const VkPipelineColorBlendAttachmentState*	pAttachments
596 			{ 1.0f, 1.0f, 1.0f, 1.0f }										// float										blendConstants[4]
597 		};
598 
599 		// Setup different stencil masks and refs in each quad
600 		for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
601 		{
602 			const StencilTest::StencilStateConfig&	config	= StencilTest::s_stencilStateConfigs[quadNdx];
603 			VkStencilOpState&						front	= depthStencilStateParams.front;
604 			VkStencilOpState&						back	= depthStencilStateParams.back;
605 
606 			front.compareMask	= config.frontReadMask;
607 			front.writeMask		= config.frontWriteMask;
608 			front.reference		= config.frontRef;
609 
610 			back.compareMask	= config.backReadMask;
611 			back.writeMask		= config.backWriteMask;
612 			back.reference		= config.backRef;
613 
614 			m_graphicsPipelines[quadNdx] = makeGraphicsPipeline(vk,																// const DeviceInterface&                        vk
615 																vkDevice,														// const VkDevice                                device
616 																*m_pipelineLayout,												// const VkPipelineLayout                        pipelineLayout
617 																*m_vertexShaderModule,											// const VkShaderModule                          vertexShaderModule
618 																DE_NULL,														// const VkShaderModule                          tessellationControlModule
619 																DE_NULL,														// const VkShaderModule                          tessellationEvalModule
620 																DE_NULL,														// const VkShaderModule                          geometryShaderModule
621 																*m_fragmentShaderModule,										// const VkShaderModule                          fragmentShaderModule
622 																*m_renderPass,													// const VkRenderPass                            renderPass
623 																viewports,														// const std::vector<VkViewport>&                viewports
624 																scissors,														// const std::vector<VkRect2D>&                  scissors
625 																VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							// const VkPrimitiveTopology                     topology
626 																0u,																// const deUint32                                subpass
627 																0u,																// const deUint32                                patchControlPoints
628 																&vertexInputStateParams,										// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
629 																&rasterizationStateParams,										// const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
630 																DE_NULL,														// const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
631 																&depthStencilStateParams,										// const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
632 																(m_colorAttachmentEnable ? DE_NULL : &colorBlendStateParams));	// const VkPipelineColorBlendStateCreateInfo*	 colorBlendStateCreateInfo
633 		}
634 	}
635 
636 
637 	// Create vertex buffer
638 	{
639 		const VkBufferCreateInfo vertexBufferParams =
640 		{
641 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
642 			DE_NULL,									// const void*			pNext;
643 			0u,											// VkBufferCreateFlags	flags;
644 			1024u,										// VkDeviceSize			size;
645 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
646 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
647 			1u,											// deUint32				queueFamilyIndexCount;
648 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
649 		};
650 
651 		m_vertices			= createOverlappingQuads();
652 		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
653 		m_vertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
654 
655 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
656 
657 		// Adjust depths
658 		for (int quadNdx = 0; quadNdx < 4; quadNdx++)
659 			for (int vertexNdx = 0; vertexNdx < 6; vertexNdx++)
660 				m_vertices[quadNdx * 6 + vertexNdx].position.z() = StencilTest::s_quadDepths[quadNdx];
661 
662 		// Load vertices into vertex buffer
663 		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
664 		flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
665 	}
666 
667 	// Create command pool
668 	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
669 
670 	// Create command buffer
671 	{
672 		const VkImageMemoryBarrier	colorImageBarrier					=
673 		{
674 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType            sType;
675 			DE_NULL,										// const void*                pNext;
676 			(VkAccessFlags)0,								// VkAccessFlags              srcAccessMask;
677 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags              dstAccessMask;
678 			VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout              oldLayout;
679 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout              newLayout;
680 			VK_QUEUE_FAMILY_IGNORED,						// uint32_t                   srcQueueFamilyIndex;
681 			VK_QUEUE_FAMILY_IGNORED,						// uint32_t                   dstQueueFamilyIndex;
682 			*m_colorImage,									// VkImage                    image;
683 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }	// VkImageSubresourceRange    subresourceRange;
684 		};
685 
686 		VkImageSubresourceRange		stencilImageBarrierSubresourceRange	= m_stencilImageSubresourceRange;
687 		VkImageLayout				newLayout							= VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
688 		if (m_separateDepthStencilLayouts)
689 		{
690 			stencilImageBarrierSubresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
691 			newLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR;
692 		}
693 
694 		const VkImageMemoryBarrier	stencilImageBarrier					=
695 		{
696 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,									// VkStructureType            sType;
697 			DE_NULL,																// const void*                pNext;
698 			(VkAccessFlags)0,														// VkAccessFlags              srcAccessMask;
699 			VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,							// VkAccessFlags              dstAccessMask;
700 			VK_IMAGE_LAYOUT_UNDEFINED,												// VkImageLayout              oldLayout;
701 			newLayout,																// VkImageLayout              newLayout;
702 			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   srcQueueFamilyIndex;
703 			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   dstQueueFamilyIndex;
704 			*m_stencilImage,														// VkImage                    image;
705 			stencilImageBarrierSubresourceRange,									// VkImageSubresourceRange    subresourceRange;
706 		};
707 
708 		std::vector<VkClearValue>			attachmentClearValues;
709 		std::vector<VkImageMemoryBarrier>	imageLayoutBarriers;
710 
711 		if (m_colorAttachmentEnable)
712 		{
713 			attachmentClearValues.push_back(defaultClearValue(m_colorFormat));
714 			imageLayoutBarriers.push_back(colorImageBarrier);
715 		}
716 
717 		attachmentClearValues.push_back(defaultClearValue(m_stencilFormat));
718 		imageLayoutBarriers.push_back(stencilImageBarrier);
719 
720 		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
721 
722 		beginCommandBuffer(vk, *m_cmdBuffer, 0u);
723 
724 		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,
725 			0u, DE_NULL, 0u, DE_NULL, (deUint32)imageLayoutBarriers.size(), imageLayoutBarriers.data());
726 
727 		beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), (deUint32)attachmentClearValues.size(), attachmentClearValues.data());
728 
729 		const VkDeviceSize		quadOffset		= (m_vertices.size() / StencilTest::QUAD_COUNT) * sizeof(Vertex4RGBA);
730 
731 		for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
732 		{
733 			VkDeviceSize vertexBufferOffset = quadOffset * quadNdx;
734 
735 			vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelines[quadNdx]);
736 			vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
737 			vk.cmdDraw(*m_cmdBuffer, (deUint32)(m_vertices.size() / StencilTest::QUAD_COUNT), 1, 0, 0);
738 		}
739 
740 		endRenderPass(vk, *m_cmdBuffer);
741 		endCommandBuffer(vk, *m_cmdBuffer);
742 	}
743 }
744 
~StencilTestInstance(void)745 StencilTestInstance::~StencilTestInstance (void)
746 {
747 }
748 
iterate(void)749 tcu::TestStatus StencilTestInstance::iterate (void)
750 {
751 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
752 	const VkDevice				vkDevice	= m_context.getDevice();
753 	const VkQueue				queue		= m_context.getUniversalQueue();
754 
755 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
756 
757 	return verifyImage();
758 }
759 
verifyImage(void)760 tcu::TestStatus StencilTestInstance::verifyImage (void)
761 {
762 	const tcu::TextureFormat	tcuColorFormat		= mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM);
763 	const tcu::TextureFormat	tcuStencilFormat	= mapVkFormat(m_stencilFormat);
764 	const ColorVertexShader		vertexShader;
765 	const ColorFragmentShader	fragmentShader		(tcuColorFormat, tcuStencilFormat);
766 	const rr::Program			program				(&vertexShader, &fragmentShader);
767 	ReferenceRenderer			refRenderer			(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuStencilFormat, &program);
768 	bool						colorCompareOk		= false;
769 	bool						stencilCompareOk	= false;
770 
771 	// Render reference image
772 	{
773 		// Set depth state
774 		rr::RenderState renderState(refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits);
775 
776 		renderState.fragOps.depthTestEnabled	= true;
777 		renderState.fragOps.depthFunc			= mapVkCompareOp(VK_COMPARE_OP_LESS);
778 		renderState.fragOps.stencilTestEnabled	= true;
779 
780 		rr::StencilState& refStencilFront	= renderState.fragOps.stencilStates[rr::FACETYPE_FRONT];
781 		rr::StencilState& refStencilBack	= renderState.fragOps.stencilStates[rr::FACETYPE_BACK];
782 
783 		refStencilFront.sFail		= mapVkStencilOp(m_stencilOpStateFront.failOp);
784 		refStencilFront.dpFail		= mapVkStencilOp(m_stencilOpStateFront.depthFailOp);
785 		refStencilFront.dpPass		= mapVkStencilOp(m_stencilOpStateFront.passOp);
786 		refStencilFront.func		= mapVkCompareOp(m_stencilOpStateFront.compareOp);
787 
788 		refStencilBack.sFail		= mapVkStencilOp(m_stencilOpStateBack.failOp);
789 		refStencilBack.dpPass		= mapVkStencilOp(m_stencilOpStateBack.passOp);
790 		refStencilBack.dpFail		= mapVkStencilOp(m_stencilOpStateBack.depthFailOp);
791 		refStencilBack.func			= mapVkCompareOp(m_stencilOpStateBack.compareOp);
792 
793 		// Reverse winding of vertices, as Vulkan screen coordinates start at upper left
794 		std::vector<Vertex4RGBA> cwVertices(m_vertices);
795 		for (size_t vertexNdx = 0; vertexNdx < cwVertices.size() - 2; vertexNdx += 3)
796 		{
797 			const Vertex4RGBA cwVertex1	= cwVertices[vertexNdx + 1];
798 
799 			cwVertices[vertexNdx + 1]	= cwVertices[vertexNdx + 2];
800 			cwVertices[vertexNdx + 2]	= cwVertex1;
801 		}
802 
803 		for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
804 		{
805 			refStencilFront.ref			= (int)StencilTest::s_stencilStateConfigs[quadNdx].frontRef;
806 			refStencilFront.compMask	= StencilTest::s_stencilStateConfigs[quadNdx].frontReadMask;
807 			refStencilFront.writeMask	= StencilTest::s_stencilStateConfigs[quadNdx].frontWriteMask;
808 
809 			refStencilBack.ref			= (int)StencilTest::s_stencilStateConfigs[quadNdx].backRef;
810 			refStencilBack.compMask		= StencilTest::s_stencilStateConfigs[quadNdx].backReadMask;
811 			refStencilBack.writeMask	= StencilTest::s_stencilStateConfigs[quadNdx].backWriteMask;
812 
813 			refRenderer.draw(renderState,
814 							 rr::PRIMITIVETYPE_TRIANGLES,
815 							 std::vector<Vertex4RGBA>(cwVertices.begin() + quadNdx * 6,
816 													  cwVertices.begin() + (quadNdx + 1) * 6));
817 		}
818 	}
819 
820 	// Compare result with reference image
821 	if (m_colorAttachmentEnable)
822 	{
823 		const DeviceInterface&				vk					= m_context.getDeviceInterface();
824 		const VkDevice						vkDevice			= m_context.getDevice();
825 		const VkQueue						queue				= m_context.getUniversalQueue();
826 		const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
827 		SimpleAllocator						allocator			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
828 		de::UniquePtr<tcu::TextureLevel>	result				(readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize).release());
829 
830 		colorCompareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
831 																   "IntImageCompare",
832 																   "Image comparison",
833 																   refRenderer.getAccess(),
834 																   result->getAccess(),
835 																   tcu::UVec4(2, 2, 2, 2),
836 																   tcu::IVec3(1, 1, 0),
837 																   true,
838 																   tcu::COMPARE_LOG_RESULT);
839 	}
840 	else
841 	{
842 		colorCompareOk = true;
843 	}
844 
845 	// Compare stencil result with reference image
846 	{
847 		const DeviceInterface&				vk					= m_context.getDeviceInterface();
848 		const VkDevice						vkDevice			= m_context.getDevice();
849 		const VkQueue						queue				= m_context.getUniversalQueue();
850 		const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
851 		SimpleAllocator						allocator			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
852 		de::UniquePtr<tcu::TextureLevel>	result				(readStencilAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_stencilImage, m_stencilFormat, m_renderSize).release());
853 
854 		{
855 			const tcu::PixelBufferAccess stencilAccess (tcu::getEffectiveDepthStencilAccess(refRenderer.getDepthStencilAccess(), tcu::Sampler::MODE_STENCIL));
856 			stencilCompareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
857 																		 "StencilImageCompare",
858 																		 "Stencil image comparison",
859 																		 stencilAccess,
860 																		 result->getAccess(),
861 																		 tcu::UVec4(2, 2, 2, 2),
862 																		 tcu::IVec3(1, 1, 0),
863 																		 true,
864 																		 tcu::COMPARE_LOG_RESULT);
865 		}
866 	}
867 
868 	if (colorCompareOk && stencilCompareOk)
869 		return tcu::TestStatus::pass("Result image matches reference");
870 	else
871 		return tcu::TestStatus::fail("Image mismatch");
872 }
873 
874 
875 // Utilities for test names
876 
getShortName(VkStencilOp stencilOp)877 const char* getShortName (VkStencilOp stencilOp)
878 {
879 	switch (stencilOp)
880 	{
881 		case VK_STENCIL_OP_KEEP:					return "keep";
882 		case VK_STENCIL_OP_ZERO:					return "zero";
883 		case VK_STENCIL_OP_REPLACE:					return "repl";
884 		case VK_STENCIL_OP_INCREMENT_AND_CLAMP:		return "incc";
885 		case VK_STENCIL_OP_DECREMENT_AND_CLAMP:		return "decc";
886 		case VK_STENCIL_OP_INVERT:					return "inv";
887 		case VK_STENCIL_OP_INCREMENT_AND_WRAP:		return "wrap";
888 		case VK_STENCIL_OP_DECREMENT_AND_WRAP:		return "decw";
889 
890 		default:
891 			DE_FATAL("Invalid VkStencilOpState value");
892 	}
893 	return DE_NULL;
894 }
895 
getStencilStateSetDescription(const VkStencilOpState & stencilOpStateFront,const VkStencilOpState & stencilOpStateBack)896 std::string getStencilStateSetDescription(const VkStencilOpState& stencilOpStateFront,
897 										  const VkStencilOpState& stencilOpStateBack)
898 {
899 	std::ostringstream desc;
900 
901 	desc << "\nFront faces:\n" << stencilOpStateFront;
902 	desc << "Back faces:\n" << stencilOpStateBack;
903 
904 	return desc.str();
905 }
906 
getFormatCaseName(VkFormat format)907 std::string getFormatCaseName (VkFormat format)
908 {
909 	const std::string fullName = getFormatName(format);
910 
911 	DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
912 
913 	return de::toLower(fullName.substr(10));
914 }
915 
916 } // anonymous
917 
createStencilTests(tcu::TestContext & testCtx)918 tcu::TestCaseGroup* createStencilTests (tcu::TestContext& testCtx)
919 {
920 	const VkFormat stencilFormats[] =
921 	{
922 		VK_FORMAT_S8_UINT,
923 		VK_FORMAT_D16_UNORM_S8_UINT,
924 		VK_FORMAT_D24_UNORM_S8_UINT,
925 		VK_FORMAT_D32_SFLOAT_S8_UINT
926 	};
927 
928 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(compareOps) == 8);
929 	DE_STATIC_ASSERT(vk::VK_COMPARE_OP_LAST == 8);
930 
931 	static const char* compareOpNames[8] =
932 	{
933 		"comp_never",
934 		"comp_less",
935 		"comp_equal",
936 		"comp_less_or_equal",
937 		"comp_greater",
938 		"comp_not_equal",
939 		"comp_greater_or_equal",
940 		"comp_always"
941 	};
942 
943 	de::MovePtr<tcu::TestCaseGroup>		stencilTests				(new tcu::TestCaseGroup(testCtx, "stencil", "Stencil tests"));
944 	de::MovePtr<tcu::TestCaseGroup>		noColorAttachmentTests		(new tcu::TestCaseGroup(testCtx, "nocolor", "Stencil tests with no color attachment"));
945 	const bool							colorAttachmentEnabled[]	= { true, false };
946 
947 	for (deUint32 colorAttachmentEnabledIdx = 0; colorAttachmentEnabledIdx < DE_LENGTH_OF_ARRAY(colorAttachmentEnabled); colorAttachmentEnabledIdx++)
948 	{
949 		const bool							colorEnabled				= colorAttachmentEnabled[colorAttachmentEnabledIdx];
950 		de::MovePtr<tcu::TestCaseGroup>		formatTests					(new tcu::TestCaseGroup(testCtx, "format", "Uses different stencil formats"));
951 		StencilOpStateUniqueRandomIterator	stencilOpItr				(123);
952 
953 		for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(stencilFormats); formatNdx++)
954 		{
955 			const VkFormat	stencilFormat				= stencilFormats[formatNdx];
956 			const bool		hasDepth					= tcu::hasDepthComponent(mapVkFormat(stencilFormat).order);
957 			const bool		hasStencil					= tcu::hasStencilComponent(mapVkFormat(stencilFormat).order);
958 			const int		separateLayoutsLoopCount	= (hasDepth && hasStencil) ? 2 : 1;
959 
960 			for (int separateDepthStencilLayouts = 0; separateDepthStencilLayouts < separateLayoutsLoopCount; ++separateDepthStencilLayouts)
961 			{
962 				const bool			useSeparateDepthStencilLayouts	= bool(separateDepthStencilLayouts);
963 
964 				de::MovePtr<tcu::TestCaseGroup>	formatTest		(new tcu::TestCaseGroup(testCtx,
965 																						(getFormatCaseName(stencilFormat) + ((useSeparateDepthStencilLayouts) ? "_separate_layouts" : "")).c_str(),
966 																						(std::string("Uses format ") + getFormatName(stencilFormat) + ((useSeparateDepthStencilLayouts) ? " with separate depth/stencil layouts" : "")).c_str()));
967 
968 				de::MovePtr<tcu::TestCaseGroup>	stencilStateTests;
969 				{
970 					std::ostringstream desc;
971 					desc << "Draws 4 quads with the following depths and dynamic stencil states: ";
972 
973 					for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
974 					{
975 						const StencilTest::StencilStateConfig& stencilConfig = StencilTest::s_stencilStateConfigs[quadNdx];
976 
977 						desc << "(" << quadNdx << ") "
978 							 << "z = " << StencilTest::s_quadDepths[quadNdx] << ", "
979 							 << "frontReadMask = " << stencilConfig.frontReadMask << ", "
980 							 << "frontWriteMask = " << stencilConfig.frontWriteMask << ", "
981 							 << "frontRef = " << stencilConfig.frontRef << ", "
982 							 << "backReadMask = " << stencilConfig.backReadMask << ", "
983 							 << "backWriteMask = " << stencilConfig.backWriteMask << ", "
984 							 << "backRef = " << stencilConfig.backRef;
985 					}
986 
987 					stencilStateTests = de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, "states", desc.str().c_str()));
988 				}
989 
990 				stencilOpItr.reset();
991 
992 				for (deUint32 failOpNdx = 0u; failOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); failOpNdx++)
993 				{
994 					const std::string				failOpName	= std::string("fail_") + getShortName(stencilOps[failOpNdx]);
995 					de::MovePtr<tcu::TestCaseGroup>	failOpTest	(new tcu::TestCaseGroup(testCtx, failOpName.c_str(), ""));
996 
997 					for (deUint32 passOpNdx = 0u; passOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); passOpNdx++)
998 					{
999 						const std::string				passOpName	= std::string("pass_") + getShortName(stencilOps[passOpNdx]);
1000 						de::MovePtr<tcu::TestCaseGroup>	passOpTest	(new tcu::TestCaseGroup(testCtx, passOpName.c_str(), ""));
1001 
1002 						for (deUint32 dFailOpNdx = 0u; dFailOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); dFailOpNdx++)
1003 						{
1004 							const std::string				dFailOpName	= std::string("dfail_") + getShortName(stencilOps[dFailOpNdx]);
1005 							de::MovePtr<tcu::TestCaseGroup>	dFailOpTest	(new tcu::TestCaseGroup(testCtx, dFailOpName.c_str(), ""));
1006 
1007 							for (deUint32 compareOpNdx = 0u; compareOpNdx < DE_LENGTH_OF_ARRAY(compareOps); compareOpNdx++)
1008 							{
1009 								// Iterate front set of stencil state in ascending order
1010 								const VkStencilOpState	stencilStateFront	=
1011 								{
1012 									stencilOps[failOpNdx],		// failOp
1013 									stencilOps[passOpNdx],		// passOp
1014 									stencilOps[dFailOpNdx],		// depthFailOp
1015 									compareOps[compareOpNdx],	// compareOp
1016 									0x0,						// compareMask
1017 									0x0,						// writeMask
1018 									0x0							// reference
1019 								};
1020 
1021 								// Iterate back set of stencil state in random order
1022 								const VkStencilOpState	stencilStateBack	= stencilOpItr.next();
1023 								const std::string		caseName			= compareOpNames[compareOpNdx];
1024 								const std::string		caseDesc			= getStencilStateSetDescription(stencilStateFront, stencilStateBack);
1025 
1026 								dFailOpTest->addChild(new StencilTest(testCtx, caseName, caseDesc, stencilFormat, stencilStateFront, stencilStateBack, colorEnabled, useSeparateDepthStencilLayouts));
1027 							}
1028 							passOpTest->addChild(dFailOpTest.release());
1029 						}
1030 						failOpTest->addChild(passOpTest.release());
1031 					}
1032 					stencilStateTests->addChild(failOpTest.release());
1033 				}
1034 
1035 				formatTest->addChild(stencilStateTests.release());
1036 				formatTests->addChild(formatTest.release());
1037 			}
1038 		}
1039 
1040 		if (colorEnabled)
1041 			stencilTests->addChild(formatTests.release());
1042 		else
1043 			noColorAttachmentTests->addChild(formatTests.release());
1044 	}
1045 
1046 	stencilTests->addChild(noColorAttachmentTests.release());
1047 
1048 	return stencilTests.release();
1049 }
1050 
1051 } // pipeline
1052 } // vkt
1053