• 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 		// Setup different stencil masks and refs in each quad
588 		for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
589 		{
590 			const StencilTest::StencilStateConfig&	config	= StencilTest::s_stencilStateConfigs[quadNdx];
591 			VkStencilOpState&						front	= depthStencilStateParams.front;
592 			VkStencilOpState&						back	= depthStencilStateParams.back;
593 
594 			front.compareMask	= config.frontReadMask;
595 			front.writeMask		= config.frontWriteMask;
596 			front.reference		= config.frontRef;
597 
598 			back.compareMask	= config.backReadMask;
599 			back.writeMask		= config.backWriteMask;
600 			back.reference		= config.backRef;
601 
602 			m_graphicsPipelines[quadNdx] = makeGraphicsPipeline(vk,										// const DeviceInterface&                        vk
603 																vkDevice,								// const VkDevice                                device
604 																*m_pipelineLayout,						// const VkPipelineLayout                        pipelineLayout
605 																*m_vertexShaderModule,					// const VkShaderModule                          vertexShaderModule
606 																DE_NULL,								// const VkShaderModule                          tessellationControlModule
607 																DE_NULL,								// const VkShaderModule                          tessellationEvalModule
608 																DE_NULL,								// const VkShaderModule                          geometryShaderModule
609 																*m_fragmentShaderModule,				// const VkShaderModule                          fragmentShaderModule
610 																*m_renderPass,							// const VkRenderPass                            renderPass
611 																viewports,								// const std::vector<VkViewport>&                viewports
612 																scissors,								// const std::vector<VkRect2D>&                  scissors
613 																VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology                     topology
614 																0u,										// const deUint32                                subpass
615 																0u,										// const deUint32                                patchControlPoints
616 																&vertexInputStateParams,				// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
617 																&rasterizationStateParams,				// const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
618 																DE_NULL,								// const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
619 																&depthStencilStateParams);				// const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
620 		}
621 	}
622 
623 
624 	// Create vertex buffer
625 	{
626 		const VkBufferCreateInfo vertexBufferParams =
627 		{
628 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
629 			DE_NULL,									// const void*			pNext;
630 			0u,											// VkBufferCreateFlags	flags;
631 			1024u,										// VkDeviceSize			size;
632 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
633 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
634 			1u,											// deUint32				queueFamilyIndexCount;
635 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
636 		};
637 
638 		m_vertices			= createOverlappingQuads();
639 		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
640 		m_vertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
641 
642 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
643 
644 		// Adjust depths
645 		for (int quadNdx = 0; quadNdx < 4; quadNdx++)
646 			for (int vertexNdx = 0; vertexNdx < 6; vertexNdx++)
647 				m_vertices[quadNdx * 6 + vertexNdx].position.z() = StencilTest::s_quadDepths[quadNdx];
648 
649 		// Load vertices into vertex buffer
650 		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
651 		flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
652 	}
653 
654 	// Create command pool
655 	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
656 
657 	// Create command buffer
658 	{
659 		const VkImageMemoryBarrier	colorImageBarrier					=
660 		{
661 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType            sType;
662 			DE_NULL,										// const void*                pNext;
663 			(VkAccessFlags)0,								// VkAccessFlags              srcAccessMask;
664 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags              dstAccessMask;
665 			VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout              oldLayout;
666 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout              newLayout;
667 			VK_QUEUE_FAMILY_IGNORED,						// uint32_t                   srcQueueFamilyIndex;
668 			VK_QUEUE_FAMILY_IGNORED,						// uint32_t                   dstQueueFamilyIndex;
669 			*m_colorImage,									// VkImage                    image;
670 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }	// VkImageSubresourceRange    subresourceRange;
671 		};
672 
673 		VkImageSubresourceRange		stencilImageBarrierSubresourceRange	= m_stencilImageSubresourceRange;
674 		VkImageLayout				newLayout							= VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
675 		if (m_separateDepthStencilLayouts)
676 		{
677 			stencilImageBarrierSubresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
678 			newLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR;
679 		}
680 
681 		const VkImageMemoryBarrier	stencilImageBarrier					=
682 		{
683 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,									// VkStructureType            sType;
684 			DE_NULL,																// const void*                pNext;
685 			(VkAccessFlags)0,														// VkAccessFlags              srcAccessMask;
686 			VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,							// VkAccessFlags              dstAccessMask;
687 			VK_IMAGE_LAYOUT_UNDEFINED,												// VkImageLayout              oldLayout;
688 			newLayout,																// VkImageLayout              newLayout;
689 			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   srcQueueFamilyIndex;
690 			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   dstQueueFamilyIndex;
691 			*m_stencilImage,														// VkImage                    image;
692 			stencilImageBarrierSubresourceRange,									// VkImageSubresourceRange    subresourceRange;
693 		};
694 
695 		std::vector<VkClearValue>			attachmentClearValues;
696 		std::vector<VkImageMemoryBarrier>	imageLayoutBarriers;
697 
698 		if (m_colorAttachmentEnable)
699 		{
700 			attachmentClearValues.push_back(defaultClearValue(m_colorFormat));
701 			imageLayoutBarriers.push_back(colorImageBarrier);
702 		}
703 
704 		attachmentClearValues.push_back(defaultClearValue(m_stencilFormat));
705 		imageLayoutBarriers.push_back(stencilImageBarrier);
706 
707 		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
708 
709 		beginCommandBuffer(vk, *m_cmdBuffer, 0u);
710 
711 		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,
712 			0u, DE_NULL, 0u, DE_NULL, (deUint32)imageLayoutBarriers.size(), imageLayoutBarriers.data());
713 
714 		beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), (deUint32)attachmentClearValues.size(), attachmentClearValues.data());
715 
716 		const VkDeviceSize		quadOffset		= (m_vertices.size() / StencilTest::QUAD_COUNT) * sizeof(Vertex4RGBA);
717 
718 		for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
719 		{
720 			VkDeviceSize vertexBufferOffset = quadOffset * quadNdx;
721 
722 			vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelines[quadNdx]);
723 			vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
724 			vk.cmdDraw(*m_cmdBuffer, (deUint32)(m_vertices.size() / StencilTest::QUAD_COUNT), 1, 0, 0);
725 		}
726 
727 		endRenderPass(vk, *m_cmdBuffer);
728 		endCommandBuffer(vk, *m_cmdBuffer);
729 	}
730 }
731 
~StencilTestInstance(void)732 StencilTestInstance::~StencilTestInstance (void)
733 {
734 }
735 
iterate(void)736 tcu::TestStatus StencilTestInstance::iterate (void)
737 {
738 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
739 	const VkDevice				vkDevice	= m_context.getDevice();
740 	const VkQueue				queue		= m_context.getUniversalQueue();
741 
742 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
743 
744 	return verifyImage();
745 }
746 
verifyImage(void)747 tcu::TestStatus StencilTestInstance::verifyImage (void)
748 {
749 	const tcu::TextureFormat	tcuColorFormat		= mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM);
750 	const tcu::TextureFormat	tcuStencilFormat	= mapVkFormat(m_stencilFormat);
751 	const ColorVertexShader		vertexShader;
752 	const ColorFragmentShader	fragmentShader		(tcuColorFormat, tcuStencilFormat);
753 	const rr::Program			program				(&vertexShader, &fragmentShader);
754 	ReferenceRenderer			refRenderer			(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuStencilFormat, &program);
755 	bool						colorCompareOk		= false;
756 	bool						stencilCompareOk	= false;
757 
758 	// Render reference image
759 	{
760 		// Set depth state
761 		rr::RenderState renderState(refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits);
762 
763 		renderState.fragOps.depthTestEnabled	= true;
764 		renderState.fragOps.depthFunc			= mapVkCompareOp(VK_COMPARE_OP_LESS);
765 		renderState.fragOps.stencilTestEnabled	= true;
766 
767 		rr::StencilState& refStencilFront	= renderState.fragOps.stencilStates[rr::FACETYPE_FRONT];
768 		rr::StencilState& refStencilBack	= renderState.fragOps.stencilStates[rr::FACETYPE_BACK];
769 
770 		refStencilFront.sFail		= mapVkStencilOp(m_stencilOpStateFront.failOp);
771 		refStencilFront.dpFail		= mapVkStencilOp(m_stencilOpStateFront.depthFailOp);
772 		refStencilFront.dpPass		= mapVkStencilOp(m_stencilOpStateFront.passOp);
773 		refStencilFront.func		= mapVkCompareOp(m_stencilOpStateFront.compareOp);
774 
775 		refStencilBack.sFail		= mapVkStencilOp(m_stencilOpStateBack.failOp);
776 		refStencilBack.dpPass		= mapVkStencilOp(m_stencilOpStateBack.passOp);
777 		refStencilBack.dpFail		= mapVkStencilOp(m_stencilOpStateBack.depthFailOp);
778 		refStencilBack.func			= mapVkCompareOp(m_stencilOpStateBack.compareOp);
779 
780 		// Reverse winding of vertices, as Vulkan screen coordinates start at upper left
781 		std::vector<Vertex4RGBA> cwVertices(m_vertices);
782 		for (size_t vertexNdx = 0; vertexNdx < cwVertices.size() - 2; vertexNdx += 3)
783 		{
784 			const Vertex4RGBA cwVertex1	= cwVertices[vertexNdx + 1];
785 
786 			cwVertices[vertexNdx + 1]	= cwVertices[vertexNdx + 2];
787 			cwVertices[vertexNdx + 2]	= cwVertex1;
788 		}
789 
790 		for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
791 		{
792 			refStencilFront.ref			= (int)StencilTest::s_stencilStateConfigs[quadNdx].frontRef;
793 			refStencilFront.compMask	= StencilTest::s_stencilStateConfigs[quadNdx].frontReadMask;
794 			refStencilFront.writeMask	= StencilTest::s_stencilStateConfigs[quadNdx].frontWriteMask;
795 
796 			refStencilBack.ref			= (int)StencilTest::s_stencilStateConfigs[quadNdx].backRef;
797 			refStencilBack.compMask		= StencilTest::s_stencilStateConfigs[quadNdx].backReadMask;
798 			refStencilBack.writeMask	= StencilTest::s_stencilStateConfigs[quadNdx].backWriteMask;
799 
800 			refRenderer.draw(renderState,
801 							 rr::PRIMITIVETYPE_TRIANGLES,
802 							 std::vector<Vertex4RGBA>(cwVertices.begin() + quadNdx * 6,
803 													  cwVertices.begin() + (quadNdx + 1) * 6));
804 		}
805 	}
806 
807 	// Compare result with reference image
808 	if (m_colorAttachmentEnable)
809 	{
810 		const DeviceInterface&				vk					= m_context.getDeviceInterface();
811 		const VkDevice						vkDevice			= m_context.getDevice();
812 		const VkQueue						queue				= m_context.getUniversalQueue();
813 		const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
814 		SimpleAllocator						allocator			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
815 		de::UniquePtr<tcu::TextureLevel>	result				(readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize).release());
816 
817 		colorCompareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
818 																   "IntImageCompare",
819 																   "Image comparison",
820 																   refRenderer.getAccess(),
821 																   result->getAccess(),
822 																   tcu::UVec4(2, 2, 2, 2),
823 																   tcu::IVec3(1, 1, 0),
824 																   true,
825 																   tcu::COMPARE_LOG_RESULT);
826 	}
827 	else
828 	{
829 		colorCompareOk = true;
830 	}
831 
832 	// Compare stencil result with reference image
833 	{
834 		const DeviceInterface&				vk					= m_context.getDeviceInterface();
835 		const VkDevice						vkDevice			= m_context.getDevice();
836 		const VkQueue						queue				= m_context.getUniversalQueue();
837 		const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
838 		SimpleAllocator						allocator			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
839 		de::UniquePtr<tcu::TextureLevel>	result				(readStencilAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_stencilImage, m_stencilFormat, m_renderSize).release());
840 
841 		{
842 			const tcu::PixelBufferAccess stencilAccess (tcu::getEffectiveDepthStencilAccess(refRenderer.getDepthStencilAccess(), tcu::Sampler::MODE_STENCIL));
843 			stencilCompareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
844 																		 "StencilImageCompare",
845 																		 "Stencil image comparison",
846 																		 stencilAccess,
847 																		 result->getAccess(),
848 																		 tcu::UVec4(2, 2, 2, 2),
849 																		 tcu::IVec3(1, 1, 0),
850 																		 true,
851 																		 tcu::COMPARE_LOG_RESULT);
852 		}
853 	}
854 
855 	if (colorCompareOk && stencilCompareOk)
856 		return tcu::TestStatus::pass("Result image matches reference");
857 	else
858 		return tcu::TestStatus::fail("Image mismatch");
859 }
860 
861 
862 // Utilities for test names
863 
getShortName(VkStencilOp stencilOp)864 const char* getShortName (VkStencilOp stencilOp)
865 {
866 	switch (stencilOp)
867 	{
868 		case VK_STENCIL_OP_KEEP:					return "keep";
869 		case VK_STENCIL_OP_ZERO:					return "zero";
870 		case VK_STENCIL_OP_REPLACE:					return "repl";
871 		case VK_STENCIL_OP_INCREMENT_AND_CLAMP:		return "incc";
872 		case VK_STENCIL_OP_DECREMENT_AND_CLAMP:		return "decc";
873 		case VK_STENCIL_OP_INVERT:					return "inv";
874 		case VK_STENCIL_OP_INCREMENT_AND_WRAP:		return "wrap";
875 		case VK_STENCIL_OP_DECREMENT_AND_WRAP:		return "decw";
876 
877 		default:
878 			DE_FATAL("Invalid VkStencilOpState value");
879 	}
880 	return DE_NULL;
881 }
882 
getStencilStateSetDescription(const VkStencilOpState & stencilOpStateFront,const VkStencilOpState & stencilOpStateBack)883 std::string getStencilStateSetDescription(const VkStencilOpState& stencilOpStateFront,
884 										  const VkStencilOpState& stencilOpStateBack)
885 {
886 	std::ostringstream desc;
887 
888 	desc << "\nFront faces:\n" << stencilOpStateFront;
889 	desc << "Back faces:\n" << stencilOpStateBack;
890 
891 	return desc.str();
892 }
893 
getFormatCaseName(VkFormat format)894 std::string getFormatCaseName (VkFormat format)
895 {
896 	const std::string fullName = getFormatName(format);
897 
898 	DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
899 
900 	return de::toLower(fullName.substr(10));
901 }
902 
903 } // anonymous
904 
createStencilTests(tcu::TestContext & testCtx)905 tcu::TestCaseGroup* createStencilTests (tcu::TestContext& testCtx)
906 {
907 	const VkFormat stencilFormats[] =
908 	{
909 		VK_FORMAT_S8_UINT,
910 		VK_FORMAT_D16_UNORM_S8_UINT,
911 		VK_FORMAT_D24_UNORM_S8_UINT,
912 		VK_FORMAT_D32_SFLOAT_S8_UINT
913 	};
914 
915 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(compareOps) == 8);
916 	DE_STATIC_ASSERT(vk::VK_COMPARE_OP_LAST == 8);
917 
918 	static const char* compareOpNames[8] =
919 	{
920 		"comp_never",
921 		"comp_less",
922 		"comp_equal",
923 		"comp_less_or_equal",
924 		"comp_greater",
925 		"comp_not_equal",
926 		"comp_greater_or_equal",
927 		"comp_always"
928 	};
929 
930 	de::MovePtr<tcu::TestCaseGroup>		stencilTests				(new tcu::TestCaseGroup(testCtx, "stencil", "Stencil tests"));
931 	de::MovePtr<tcu::TestCaseGroup>		noColorAttachmentTests		(new tcu::TestCaseGroup(testCtx, "nocolor", "Stencil tests with no color attachment"));
932 	const bool							colorAttachmentEnabled[]	= { true, false };
933 
934 	for (deUint32 colorAttachmentEnabledIdx = 0; colorAttachmentEnabledIdx < DE_LENGTH_OF_ARRAY(colorAttachmentEnabled); colorAttachmentEnabledIdx++)
935 	{
936 		const bool							colorEnabled				= colorAttachmentEnabled[colorAttachmentEnabledIdx];
937 		de::MovePtr<tcu::TestCaseGroup>		formatTests					(new tcu::TestCaseGroup(testCtx, "format", "Uses different stencil formats"));
938 		StencilOpStateUniqueRandomIterator	stencilOpItr				(123);
939 
940 		for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(stencilFormats); formatNdx++)
941 		{
942 			const VkFormat	stencilFormat				= stencilFormats[formatNdx];
943 			const bool		hasDepth					= tcu::hasDepthComponent(mapVkFormat(stencilFormat).order);
944 			const bool		hasStencil					= tcu::hasStencilComponent(mapVkFormat(stencilFormat).order);
945 			const int		separateLayoutsLoopCount	= (hasDepth && hasStencil) ? 2 : 1;
946 
947 			for (int separateDepthStencilLayouts = 0; separateDepthStencilLayouts < separateLayoutsLoopCount; ++separateDepthStencilLayouts)
948 			{
949 				const bool			useSeparateDepthStencilLayouts	= bool(separateDepthStencilLayouts);
950 
951 				de::MovePtr<tcu::TestCaseGroup>	formatTest		(new tcu::TestCaseGroup(testCtx,
952 																						(getFormatCaseName(stencilFormat) + ((useSeparateDepthStencilLayouts) ? "_separate_layouts" : "")).c_str(),
953 																						(std::string("Uses format ") + getFormatName(stencilFormat) + ((useSeparateDepthStencilLayouts) ? " with separate depth/stencil layouts" : "")).c_str()));
954 
955 				de::MovePtr<tcu::TestCaseGroup>	stencilStateTests;
956 				{
957 					std::ostringstream desc;
958 					desc << "Draws 4 quads with the following depths and dynamic stencil states: ";
959 
960 					for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
961 					{
962 						const StencilTest::StencilStateConfig& stencilConfig = StencilTest::s_stencilStateConfigs[quadNdx];
963 
964 						desc << "(" << quadNdx << ") "
965 							 << "z = " << StencilTest::s_quadDepths[quadNdx] << ", "
966 							 << "frontReadMask = " << stencilConfig.frontReadMask << ", "
967 							 << "frontWriteMask = " << stencilConfig.frontWriteMask << ", "
968 							 << "frontRef = " << stencilConfig.frontRef << ", "
969 							 << "backReadMask = " << stencilConfig.backReadMask << ", "
970 							 << "backWriteMask = " << stencilConfig.backWriteMask << ", "
971 							 << "backRef = " << stencilConfig.backRef;
972 					}
973 
974 					stencilStateTests = de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, "states", desc.str().c_str()));
975 				}
976 
977 				stencilOpItr.reset();
978 
979 				for (deUint32 failOpNdx = 0u; failOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); failOpNdx++)
980 				{
981 					const std::string				failOpName	= std::string("fail_") + getShortName(stencilOps[failOpNdx]);
982 					de::MovePtr<tcu::TestCaseGroup>	failOpTest	(new tcu::TestCaseGroup(testCtx, failOpName.c_str(), ""));
983 
984 					for (deUint32 passOpNdx = 0u; passOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); passOpNdx++)
985 					{
986 						const std::string				passOpName	= std::string("pass_") + getShortName(stencilOps[passOpNdx]);
987 						de::MovePtr<tcu::TestCaseGroup>	passOpTest	(new tcu::TestCaseGroup(testCtx, passOpName.c_str(), ""));
988 
989 						for (deUint32 dFailOpNdx = 0u; dFailOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); dFailOpNdx++)
990 						{
991 							const std::string				dFailOpName	= std::string("dfail_") + getShortName(stencilOps[dFailOpNdx]);
992 							de::MovePtr<tcu::TestCaseGroup>	dFailOpTest	(new tcu::TestCaseGroup(testCtx, dFailOpName.c_str(), ""));
993 
994 							for (deUint32 compareOpNdx = 0u; compareOpNdx < DE_LENGTH_OF_ARRAY(compareOps); compareOpNdx++)
995 							{
996 								// Iterate front set of stencil state in ascending order
997 								const VkStencilOpState	stencilStateFront	=
998 								{
999 									stencilOps[failOpNdx],		// failOp
1000 									stencilOps[passOpNdx],		// passOp
1001 									stencilOps[dFailOpNdx],		// depthFailOp
1002 									compareOps[compareOpNdx],	// compareOp
1003 									0x0,						// compareMask
1004 									0x0,						// writeMask
1005 									0x0							// reference
1006 								};
1007 
1008 								// Iterate back set of stencil state in random order
1009 								const VkStencilOpState	stencilStateBack	= stencilOpItr.next();
1010 								const std::string		caseName			= compareOpNames[compareOpNdx];
1011 								const std::string		caseDesc			= getStencilStateSetDescription(stencilStateFront, stencilStateBack);
1012 
1013 								dFailOpTest->addChild(new StencilTest(testCtx, caseName, caseDesc, stencilFormat, stencilStateFront, stencilStateBack, colorEnabled, useSeparateDepthStencilLayouts));
1014 							}
1015 							passOpTest->addChild(dFailOpTest.release());
1016 						}
1017 						failOpTest->addChild(passOpTest.release());
1018 					}
1019 					stencilStateTests->addChild(failOpTest.release());
1020 				}
1021 
1022 				formatTest->addChild(stencilStateTests.release());
1023 				formatTests->addChild(formatTest.release());
1024 			}
1025 		}
1026 
1027 		if (colorEnabled)
1028 			stencilTests->addChild(formatTests.release());
1029 		else
1030 			noColorAttachmentTests->addChild(formatTests.release());
1031 	}
1032 
1033 	stencilTests->addChild(noColorAttachmentTests.release());
1034 
1035 	return stencilTests.release();
1036 }
1037 
1038 } // pipeline
1039 } // vkt
1040