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