• 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 class StencilTest : public vkt::TestCase
90 {
91 public:
92 	enum
93 	{
94 		QUAD_COUNT = 4
95 	};
96 
97 	struct StencilStateConfig
98 	{
99 		deUint32	frontReadMask;
100 		deUint32	frontWriteMask;
101 		deUint32	frontRef;
102 
103 		deUint32	backReadMask;
104 		deUint32	backWriteMask;
105 		deUint32	backRef;
106 	};
107 
108 	const static StencilStateConfig			s_stencilStateConfigs[QUAD_COUNT];
109 	const static float						s_quadDepths[QUAD_COUNT];
110 
111 
112 											StencilTest				(tcu::TestContext&			testContext,
113 																	 const std::string&			name,
114 																	 const std::string&			description,
115 																	 PipelineConstructionType	pipelineConstructionType,
116 																	 VkFormat					stencilFormat,
117 																	 const VkStencilOpState&	stencilOpStateFront,
118 																	 const VkStencilOpState&	stencilOpStateBack,
119 																	 const bool					colorAttachmentEnable,
120 																	 const bool					separateDepthStencilLayouts);
121 	virtual									~StencilTest			(void) = default;
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 	PipelineConstructionType				m_pipelineConstructionType;
128 	VkFormat								m_stencilFormat;
129 	const VkStencilOpState					m_stencilOpStateFront;
130 	const VkStencilOpState					m_stencilOpStateBack;
131 	const bool								m_colorAttachmentEnable;
132 	const bool								m_separateDepthStencilLayouts;
133 };
134 
135 class StencilTestInstance : public vkt::TestInstance
136 {
137 public:
138 										StencilTestInstance		(Context&					context,
139 																 PipelineConstructionType	pipelineConstructionType,
140 																 VkFormat					stencilFormat,
141 																 const VkStencilOpState&	stencilOpStatesFront,
142 																 const VkStencilOpState&	stencilOpStatesBack,
143 																 const bool					colorAttachmentEnable,
144 																 const bool					separateDepthStencilLayouts);
145 	virtual								~StencilTestInstance	(void) = default;
146 	virtual tcu::TestStatus				iterate					(void);
147 
148 private:
149 	tcu::TestStatus						verifyImage				(void);
150 
151 	VkStencilOpState					m_stencilOpStateFront;
152 	VkStencilOpState					m_stencilOpStateBack;
153 	const bool							m_colorAttachmentEnable;
154 	const bool							m_separateDepthStencilLayouts;
155 	const tcu::UVec2					m_renderSize;
156 	const VkFormat						m_colorFormat;
157 	const VkFormat						m_stencilFormat;
158 	VkImageSubresourceRange				m_stencilImageSubresourceRange;
159 
160 	VkImageCreateInfo					m_colorImageCreateInfo;
161 	Move<VkImage>						m_colorImage;
162 	de::MovePtr<Allocation>				m_colorImageAlloc;
163 	Move<VkImage>						m_stencilImage;
164 	de::MovePtr<Allocation>				m_stencilImageAlloc;
165 	Move<VkImageView>					m_colorAttachmentView;
166 	Move<VkImageView>					m_stencilAttachmentView;
167 	Move<VkRenderPass>					m_renderPass;
168 	Move<VkFramebuffer>					m_framebuffer;
169 
170 	Move<VkShaderModule>				m_vertexShaderModule;
171 	Move<VkShaderModule>				m_fragmentShaderModule;
172 
173 	Move<VkBuffer>						m_vertexBuffer;
174 	std::vector<Vertex4RGBA>			m_vertices;
175 	de::MovePtr<Allocation>				m_vertexBufferAlloc;
176 
177 	Move<VkPipelineLayout>				m_pipelineLayout;
178 	GraphicsPipelineWrapper				m_graphicsPipelines[StencilTest::QUAD_COUNT];
179 
180 	Move<VkCommandPool>					m_cmdPool;
181 	Move<VkCommandBuffer>				m_cmdBuffer;
182 };
183 
184 const VkStencilOp stencilOps[] =
185 {
186 	VK_STENCIL_OP_KEEP,
187 	VK_STENCIL_OP_ZERO,
188 	VK_STENCIL_OP_REPLACE,
189 	VK_STENCIL_OP_INCREMENT_AND_CLAMP,
190 	VK_STENCIL_OP_DECREMENT_AND_CLAMP,
191 	VK_STENCIL_OP_INVERT,
192 	VK_STENCIL_OP_INCREMENT_AND_WRAP,
193 	VK_STENCIL_OP_DECREMENT_AND_WRAP
194 };
195 
196 const VkCompareOp compareOps[] =
197 {
198 	VK_COMPARE_OP_NEVER,
199 	VK_COMPARE_OP_LESS,
200 	VK_COMPARE_OP_EQUAL,
201 	VK_COMPARE_OP_LESS_OR_EQUAL,
202 	VK_COMPARE_OP_GREATER,
203 	VK_COMPARE_OP_NOT_EQUAL,
204 	VK_COMPARE_OP_GREATER_OR_EQUAL,
205 	VK_COMPARE_OP_ALWAYS
206 };
207 
208 // StencilOpStateUniqueRandomIterator
209 
210 const deUint32 StencilOpStateUniqueRandomIterator::s_stencilOpsLength		= DE_LENGTH_OF_ARRAY(stencilOps);
211 const deUint32 StencilOpStateUniqueRandomIterator::s_stencilOpsLength2		= s_stencilOpsLength * s_stencilOpsLength;
212 const deUint32 StencilOpStateUniqueRandomIterator::s_stencilOpsLength3		= s_stencilOpsLength2 * s_stencilOpsLength;
213 const deUint32 StencilOpStateUniqueRandomIterator::s_compareOpsLength		= DE_LENGTH_OF_ARRAY(compareOps);
214 const deUint32 StencilOpStateUniqueRandomIterator::s_totalStencilOpStates	= s_stencilOpsLength3 * s_compareOpsLength;
215 
StencilOpStateUniqueRandomIterator(int seed)216 StencilOpStateUniqueRandomIterator::StencilOpStateUniqueRandomIterator (int seed)
217 	: UniqueRandomIterator<VkStencilOpState>(s_totalStencilOpStates, s_totalStencilOpStates, seed)
218 {
219 }
220 
getIndexedValue(deUint32 index)221 VkStencilOpState StencilOpStateUniqueRandomIterator::getIndexedValue (deUint32 index)
222 {
223 	const deUint32 stencilCompareOpIndex = index / s_stencilOpsLength3;
224 	const deUint32 stencilCompareOpSeqIndex = stencilCompareOpIndex * s_stencilOpsLength3;
225 
226 	const deUint32 stencilDepthFailOpIndex = (index - stencilCompareOpSeqIndex) / s_stencilOpsLength2;
227 	const deUint32 stencilDepthFailOpSeqIndex = stencilDepthFailOpIndex * s_stencilOpsLength2;
228 
229 	const deUint32 stencilPassOpIndex = (index - stencilCompareOpSeqIndex - stencilDepthFailOpSeqIndex) / s_stencilOpsLength;
230 	const deUint32 stencilPassOpSeqIndex = stencilPassOpIndex * s_stencilOpsLength;
231 
232 	const deUint32 stencilFailOpIndex = index - stencilCompareOpSeqIndex - stencilDepthFailOpSeqIndex - stencilPassOpSeqIndex;
233 
234 	const VkStencilOpState stencilOpState =
235 	{
236 		stencilOps[stencilFailOpIndex],			// VkStencilOp	failOp;
237 		stencilOps[stencilPassOpIndex],			// VkStencilOp	passOp;
238 		stencilOps[stencilDepthFailOpIndex],	// VkStencilOp	depthFailOp;
239 		compareOps[stencilCompareOpIndex],		// VkCompareOp	compareOp;
240 		0x0,									// deUint32		compareMask;
241 		0x0,									// deUint32		writeMask;
242 		0x0										// deUint32		reference;
243 	};
244 
245 	return stencilOpState;
246 }
247 
248 
249 // StencilTest
250 
251 const StencilTest::StencilStateConfig StencilTest::s_stencilStateConfigs[QUAD_COUNT] =
252 {
253 	//	frontReadMask	frontWriteMask		frontRef		backReadMask	backWriteMask	backRef
254 	{	0xFF,			0xFF,				0xAB,			0xF0,			0xFF,			0xFF	},
255 	{	0xFF,			0xF0,				0xCD,			0xF0,			0xF0,			0xEF	},
256 	{	0xF0,			0x0F,				0xEF,			0xFF,			0x0F,			0xCD	},
257 	{	0xF0,			0x01,				0xFF,			0xFF,			0x01,			0xAB	}
258 };
259 
260 const float StencilTest::s_quadDepths[QUAD_COUNT] =
261 {
262 	0.1f,
263 	0.0f,
264 	0.3f,
265 	0.2f
266 };
267 
StencilTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,PipelineConstructionType pipelineConstructionType,VkFormat stencilFormat,const VkStencilOpState & stencilOpStateFront,const VkStencilOpState & stencilOpStateBack,const bool colorAttachmentEnable,const bool separateDepthStencilLayouts)268 StencilTest::StencilTest (tcu::TestContext&			testContext,
269 						  const std::string&		name,
270 						  const std::string&		description,
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, description)
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 	checkPipelineLibraryRequirements(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.getDeviceInterface(), context.getDevice(), pipelineConstructionType },
366 		{ context.getDeviceInterface(), context.getDevice(), pipelineConstructionType },
367 		{ context.getDeviceInterface(), context.getDevice(), pipelineConstructionType },
368 		{ context.getDeviceInterface(), context.getDevice(), 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 = makeRenderPass(vk, vkDevice, m_colorFormat, m_stencilFormat);
478 
479 	// Create framebuffer
480 	{
481 		std::vector<VkImageView>		attachmentBindInfos;
482 
483 		if (m_colorAttachmentEnable)
484 			attachmentBindInfos.push_back(*m_colorAttachmentView);
485 
486 		attachmentBindInfos.push_back(*m_stencilAttachmentView);
487 
488 		const VkFramebufferCreateInfo	framebufferParams =
489 		{
490 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType			sType;
491 			DE_NULL,											// const void*				pNext;
492 			0u,													// VkFramebufferCreateFlags	flags;
493 			*m_renderPass,										// VkRenderPass				renderPass;
494 			(deUint32)attachmentBindInfos.size(),				// deUint32					attachmentCount;
495 			attachmentBindInfos.data(),							// const VkImageView*		pAttachments;
496 			(deUint32)m_renderSize.x(),							// deUint32					width;
497 			(deUint32)m_renderSize.y(),							// deUint32					height;
498 			1u													// deUint32					layers;
499 		};
500 
501 		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
502 	}
503 
504 	// Create pipeline layout
505 	{
506 		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
507 		{
508 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
509 			DE_NULL,											// const void*					pNext;
510 			0u,													// VkPipelineLayoutCreateFlags	flags;
511 			0u,													// deUint32						setLayoutCount;
512 			DE_NULL,											// const VkDescriptorSetLayout*	pSetLayouts;
513 			0u,													// deUint32						pushConstantRangeCount;
514 			DE_NULL												// const VkPushConstantRange*	pPushConstantRanges;
515 		};
516 
517 		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
518 	}
519 
520 	m_vertexShaderModule		= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
521 	if (m_colorAttachmentEnable)
522 		m_fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
523 
524 	// Create pipeline
525 	{
526 		const VkVertexInputBindingDescription vertexInputBindingDescription
527 		{
528 			0u,										// deUint32					binding;
529 			sizeof(Vertex4RGBA),					// deUint32					strideInBytes;
530 			VK_VERTEX_INPUT_RATE_VERTEX				// VkVertexInputStepRate	inputRate;
531 		};
532 
533 		const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2]
534 		{
535 			{
536 				0u,									// deUint32	location;
537 				0u,									// deUint32	binding;
538 				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
539 				0u									// deUint32	offsetInBytes;
540 			},
541 			{
542 				1u,									// deUint32	location;
543 				0u,									// deUint32	binding;
544 				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
545 				DE_OFFSET_OF(Vertex4RGBA, color),	// deUint32	offsetInBytes;
546 			}
547 		};
548 
549 		const VkPipelineVertexInputStateCreateInfo vertexInputStateParams
550 		{
551 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
552 			DE_NULL,														// const void*								pNext;
553 			0u,																// VkPipelineVertexInputStateCreateFlags	flags;
554 			1u,																// deUint32									vertexBindingDescriptionCount;
555 			&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
556 			2u,																// deUint32									vertexAttributeDescriptionCount;
557 			vertexInputAttributeDescriptions								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
558 		};
559 
560 		const std::vector<VkViewport>	viewports	{ makeViewport(m_renderSize) };
561 		const std::vector<VkRect2D>		scissors	{ makeRect2D(m_renderSize) };
562 
563 		const bool isDepthEnabled = (vk::mapVkFormat(m_stencilFormat).order != tcu::TextureFormat::S);
564 
565 		VkPipelineDepthStencilStateCreateInfo depthStencilStateParams
566 		{
567 			VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
568 			DE_NULL,													// const void*								pNext;
569 			0u,															// VkPipelineDepthStencilStateCreateFlags	flags;
570 			isDepthEnabled,												// VkBool32									depthTestEnable;
571 			isDepthEnabled,												// VkBool32									depthWriteEnable;
572 			VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
573 			false,														// VkBool32									depthBoundsTestEnable;
574 			true,														// VkBool32									stencilTestEnable;
575 			m_stencilOpStateFront,										// VkStencilOpState							front;
576 			m_stencilOpStateBack,										// VkStencilOpState							back;
577 			0.0f,														// float									minDepthBounds;
578 			1.0f														// float									maxDepthBounds;
579 		};
580 
581 		// Make sure rasterization is not disabled when the fragment shader is missing.
582 		const vk::VkPipelineRasterizationStateCreateInfo rasterizationStateParams
583 		{
584 			vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	//	VkStructureType							sType;
585 			nullptr,														//	const void*								pNext;
586 			0u,																//	VkPipelineRasterizationStateCreateFlags	flags;
587 			VK_FALSE,														//	VkBool32								depthClampEnable;
588 			VK_FALSE,														//	VkBool32								rasterizerDiscardEnable;
589 			vk::VK_POLYGON_MODE_FILL,										//	VkPolygonMode							polygonMode;
590 			vk::VK_CULL_MODE_NONE,											//	VkCullModeFlags							cullMode;
591 			vk::VK_FRONT_FACE_COUNTER_CLOCKWISE,							//	VkFrontFace								frontFace;
592 			VK_FALSE,														//	VkBool32								depthBiasEnable;
593 			0.0f,															//	float									depthBiasConstantFactor;
594 			0.0f,															//	float									depthBiasClamp;
595 			0.0f,															//	float									depthBiasSlopeFactor;
596 			1.0f,															//	float									lineWidth;
597 		};
598 
599 		const vk::VkPipelineColorBlendAttachmentState blendState
600 		{
601 			VK_FALSE,
602 			VK_BLEND_FACTOR_ONE,
603 			VK_BLEND_FACTOR_ONE,
604 			VK_BLEND_OP_ADD,
605 			VK_BLEND_FACTOR_ONE,
606 			VK_BLEND_FACTOR_ONE,
607 			VK_BLEND_OP_ADD,
608 			VK_COLOR_COMPONENT_R_BIT |
609 			VK_COLOR_COMPONENT_G_BIT |
610 			VK_COLOR_COMPONENT_B_BIT |
611 			VK_COLOR_COMPONENT_A_BIT,
612 
613 		};
614 		const vk::VkPipelineColorBlendStateCreateInfo colorBlendStateParams
615 		{
616 			vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType
617 			DE_NULL,														// const void*									pNext
618 			0u,																// VkPipelineColorBlendStateCreateFlags			flags
619 			VK_FALSE,														// VkBool32										logicOpEnable
620 			vk::VK_LOGIC_OP_CLEAR,											// VkLogicOp									logicOp
621 			m_colorAttachmentEnable ? 1u : 0u,								// deUint32										attachmentCount
622 			&blendState,													// const VkPipelineColorBlendAttachmentState*	pAttachments
623 			{ 1.0f, 1.0f, 1.0f, 1.0f }										// float										blendConstants[4]
624 		};
625 
626 		// Setup different stencil masks and refs in each quad
627 		for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
628 		{
629 			const StencilTest::StencilStateConfig&	config	= StencilTest::s_stencilStateConfigs[quadNdx];
630 			VkStencilOpState&						front	= depthStencilStateParams.front;
631 			VkStencilOpState&						back	= depthStencilStateParams.back;
632 
633 			front.compareMask	= config.frontReadMask;
634 			front.writeMask		= config.frontWriteMask;
635 			front.reference		= config.frontRef;
636 
637 			back.compareMask	= config.backReadMask;
638 			back.writeMask		= config.backWriteMask;
639 			back.reference		= config.backRef;
640 
641 			m_graphicsPipelines[quadNdx].setDefaultRasterizerDiscardEnable(!m_colorAttachmentEnable)
642 										.setDefaultMultisampleState()
643 										.setupVertexInputState(&vertexInputStateParams)
644 										.setupPreRasterizationShaderState(viewports,
645 																		  scissors,
646 																		  *m_pipelineLayout,
647 																		  *m_renderPass,
648 																		  0u,
649 																		  *m_vertexShaderModule,
650 																		  &rasterizationStateParams)
651 										.setupFragmentShaderState(*m_pipelineLayout, *m_renderPass, 0u, *m_fragmentShaderModule, &depthStencilStateParams)
652 										.setupFragmentOutputState(*m_renderPass, 0, &colorBlendStateParams)
653 										.setMonolithicPipelineLayout(*m_pipelineLayout)
654 										.buildPipeline();
655 		}
656 	}
657 
658 	// Create vertex buffer
659 	{
660 		const VkBufferCreateInfo vertexBufferParams =
661 		{
662 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
663 			DE_NULL,									// const void*			pNext;
664 			0u,											// VkBufferCreateFlags	flags;
665 			1024u,										// VkDeviceSize			size;
666 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
667 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
668 			1u,											// deUint32				queueFamilyIndexCount;
669 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
670 		};
671 
672 		m_vertices			= createOverlappingQuads();
673 		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
674 		m_vertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
675 
676 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
677 
678 		// Adjust depths
679 		for (int quadNdx = 0; quadNdx < 4; quadNdx++)
680 			for (int vertexNdx = 0; vertexNdx < 6; vertexNdx++)
681 				m_vertices[quadNdx * 6 + vertexNdx].position.z() = StencilTest::s_quadDepths[quadNdx];
682 
683 		// Load vertices into vertex buffer
684 		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
685 		flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
686 	}
687 
688 	// Create command pool
689 	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
690 
691 	// Create command buffer
692 	{
693 		const VkImageMemoryBarrier	colorImageBarrier					=
694 		{
695 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType            sType;
696 			DE_NULL,										// const void*                pNext;
697 			(VkAccessFlags)0,								// VkAccessFlags              srcAccessMask;
698 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags              dstAccessMask;
699 			VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout              oldLayout;
700 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout              newLayout;
701 			VK_QUEUE_FAMILY_IGNORED,						// uint32_t                   srcQueueFamilyIndex;
702 			VK_QUEUE_FAMILY_IGNORED,						// uint32_t                   dstQueueFamilyIndex;
703 			*m_colorImage,									// VkImage                    image;
704 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }	// VkImageSubresourceRange    subresourceRange;
705 		};
706 
707 		VkImageSubresourceRange		stencilImageBarrierSubresourceRange	= m_stencilImageSubresourceRange;
708 		VkImageLayout				newLayout							= VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
709 		if (m_separateDepthStencilLayouts)
710 		{
711 			stencilImageBarrierSubresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
712 			newLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
713 		}
714 
715 		const VkImageMemoryBarrier	stencilImageBarrier					=
716 		{
717 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,									// VkStructureType            sType;
718 			DE_NULL,																// const void*                pNext;
719 			(VkAccessFlags)0,														// VkAccessFlags              srcAccessMask;
720 			VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,							// VkAccessFlags              dstAccessMask;
721 			VK_IMAGE_LAYOUT_UNDEFINED,												// VkImageLayout              oldLayout;
722 			newLayout,																// VkImageLayout              newLayout;
723 			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   srcQueueFamilyIndex;
724 			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   dstQueueFamilyIndex;
725 			*m_stencilImage,														// VkImage                    image;
726 			stencilImageBarrierSubresourceRange,									// VkImageSubresourceRange    subresourceRange;
727 		};
728 
729 		std::vector<VkClearValue>			attachmentClearValues;
730 		std::vector<VkImageMemoryBarrier>	imageLayoutBarriers;
731 
732 		if (m_colorAttachmentEnable)
733 		{
734 			attachmentClearValues.push_back(defaultClearValue(m_colorFormat));
735 			imageLayoutBarriers.push_back(colorImageBarrier);
736 		}
737 
738 		attachmentClearValues.push_back(defaultClearValue(m_stencilFormat));
739 		imageLayoutBarriers.push_back(stencilImageBarrier);
740 
741 		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
742 
743 		beginCommandBuffer(vk, *m_cmdBuffer, 0u);
744 
745 		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,
746 			0u, DE_NULL, 0u, DE_NULL, (deUint32)imageLayoutBarriers.size(), imageLayoutBarriers.data());
747 
748 		beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), (deUint32)attachmentClearValues.size(), attachmentClearValues.data());
749 
750 		const VkDeviceSize		quadOffset		= (m_vertices.size() / StencilTest::QUAD_COUNT) * sizeof(Vertex4RGBA);
751 
752 		for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
753 		{
754 			VkDeviceSize vertexBufferOffset = quadOffset * quadNdx;
755 
756 			vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsPipelines[quadNdx].getPipeline());
757 			vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
758 			vk.cmdDraw(*m_cmdBuffer, (deUint32)(m_vertices.size() / StencilTest::QUAD_COUNT), 1, 0, 0);
759 		}
760 
761 		endRenderPass(vk, *m_cmdBuffer);
762 		endCommandBuffer(vk, *m_cmdBuffer);
763 	}
764 }
765 
iterate(void)766 tcu::TestStatus StencilTestInstance::iterate (void)
767 {
768 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
769 	const VkDevice				vkDevice	= m_context.getDevice();
770 	const VkQueue				queue		= m_context.getUniversalQueue();
771 
772 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
773 
774 	return verifyImage();
775 }
776 
verifyImage(void)777 tcu::TestStatus StencilTestInstance::verifyImage (void)
778 {
779 	const tcu::TextureFormat	tcuColorFormat		= mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM);
780 	const tcu::TextureFormat	tcuStencilFormat	= mapVkFormat(m_stencilFormat);
781 	const ColorVertexShader		vertexShader;
782 	const ColorFragmentShader	fragmentShader		(tcuColorFormat, tcuStencilFormat);
783 	const rr::Program			program				(&vertexShader, &fragmentShader);
784 	ReferenceRenderer			refRenderer			(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuStencilFormat, &program);
785 	bool						colorCompareOk		= false;
786 	bool						stencilCompareOk	= false;
787 
788 	// Render reference image
789 	{
790 		// Set depth state
791 		rr::RenderState renderState(refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits);
792 
793 		renderState.fragOps.depthTestEnabled	= true;
794 		renderState.fragOps.depthFunc			= mapVkCompareOp(VK_COMPARE_OP_LESS);
795 		renderState.fragOps.stencilTestEnabled	= true;
796 
797 		rr::StencilState& refStencilFront	= renderState.fragOps.stencilStates[rr::FACETYPE_FRONT];
798 		rr::StencilState& refStencilBack	= renderState.fragOps.stencilStates[rr::FACETYPE_BACK];
799 
800 		refStencilFront.sFail		= mapVkStencilOp(m_stencilOpStateFront.failOp);
801 		refStencilFront.dpFail		= mapVkStencilOp(m_stencilOpStateFront.depthFailOp);
802 		refStencilFront.dpPass		= mapVkStencilOp(m_stencilOpStateFront.passOp);
803 		refStencilFront.func		= mapVkCompareOp(m_stencilOpStateFront.compareOp);
804 
805 		refStencilBack.sFail		= mapVkStencilOp(m_stencilOpStateBack.failOp);
806 		refStencilBack.dpPass		= mapVkStencilOp(m_stencilOpStateBack.passOp);
807 		refStencilBack.dpFail		= mapVkStencilOp(m_stencilOpStateBack.depthFailOp);
808 		refStencilBack.func			= mapVkCompareOp(m_stencilOpStateBack.compareOp);
809 
810 		// Reverse winding of vertices, as Vulkan screen coordinates start at upper left
811 		std::vector<Vertex4RGBA> cwVertices(m_vertices);
812 		for (size_t vertexNdx = 0; vertexNdx < cwVertices.size() - 2; vertexNdx += 3)
813 		{
814 			const Vertex4RGBA cwVertex1	= cwVertices[vertexNdx + 1];
815 
816 			cwVertices[vertexNdx + 1]	= cwVertices[vertexNdx + 2];
817 			cwVertices[vertexNdx + 2]	= cwVertex1;
818 		}
819 
820 		for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
821 		{
822 			refStencilFront.ref			= (int)StencilTest::s_stencilStateConfigs[quadNdx].frontRef;
823 			refStencilFront.compMask	= StencilTest::s_stencilStateConfigs[quadNdx].frontReadMask;
824 			refStencilFront.writeMask	= StencilTest::s_stencilStateConfigs[quadNdx].frontWriteMask;
825 
826 			refStencilBack.ref			= (int)StencilTest::s_stencilStateConfigs[quadNdx].backRef;
827 			refStencilBack.compMask		= StencilTest::s_stencilStateConfigs[quadNdx].backReadMask;
828 			refStencilBack.writeMask	= StencilTest::s_stencilStateConfigs[quadNdx].backWriteMask;
829 
830 			refRenderer.draw(renderState,
831 							 rr::PRIMITIVETYPE_TRIANGLES,
832 							 std::vector<Vertex4RGBA>(cwVertices.begin() + quadNdx * 6,
833 													  cwVertices.begin() + (quadNdx + 1) * 6));
834 		}
835 	}
836 
837 	// Compare result with reference image
838 	if (m_colorAttachmentEnable)
839 	{
840 		const DeviceInterface&				vk					= m_context.getDeviceInterface();
841 		const VkDevice						vkDevice			= m_context.getDevice();
842 		const VkQueue						queue				= m_context.getUniversalQueue();
843 		const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
844 		SimpleAllocator						allocator			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
845 		de::UniquePtr<tcu::TextureLevel>	result				(readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize).release());
846 
847 		colorCompareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
848 																   "IntImageCompare",
849 																   "Image comparison",
850 																   refRenderer.getAccess(),
851 																   result->getAccess(),
852 																   tcu::UVec4(2, 2, 2, 2),
853 																   tcu::IVec3(1, 1, 0),
854 																   true,
855 																   tcu::COMPARE_LOG_RESULT);
856 	}
857 	else
858 	{
859 		colorCompareOk = true;
860 	}
861 
862 	// Compare stencil result with reference image
863 	{
864 		const DeviceInterface&				vk					= m_context.getDeviceInterface();
865 		const VkDevice						vkDevice			= m_context.getDevice();
866 		const VkQueue						queue				= m_context.getUniversalQueue();
867 		const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
868 		SimpleAllocator						allocator			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
869 		de::UniquePtr<tcu::TextureLevel>	result				(readStencilAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_stencilImage, m_stencilFormat, m_renderSize).release());
870 
871 		{
872 			const tcu::PixelBufferAccess stencilAccess (tcu::getEffectiveDepthStencilAccess(refRenderer.getDepthStencilAccess(), tcu::Sampler::MODE_STENCIL));
873 			stencilCompareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
874 																		 "StencilImageCompare",
875 																		 "Stencil image comparison",
876 																		 stencilAccess,
877 																		 result->getAccess(),
878 																		 tcu::UVec4(2, 2, 2, 2),
879 																		 tcu::IVec3(1, 1, 0),
880 																		 true,
881 																		 tcu::COMPARE_LOG_RESULT);
882 		}
883 	}
884 
885 	if (colorCompareOk && stencilCompareOk)
886 		return tcu::TestStatus::pass("Result image matches reference");
887 	else
888 		return tcu::TestStatus::fail("Image mismatch");
889 }
890 
891 
892 // Utilities for test names
893 
getShortName(VkStencilOp stencilOp)894 const char* getShortName (VkStencilOp stencilOp)
895 {
896 	switch (stencilOp)
897 	{
898 		case VK_STENCIL_OP_KEEP:					return "keep";
899 		case VK_STENCIL_OP_ZERO:					return "zero";
900 		case VK_STENCIL_OP_REPLACE:					return "repl";
901 		case VK_STENCIL_OP_INCREMENT_AND_CLAMP:		return "incc";
902 		case VK_STENCIL_OP_DECREMENT_AND_CLAMP:		return "decc";
903 		case VK_STENCIL_OP_INVERT:					return "inv";
904 		case VK_STENCIL_OP_INCREMENT_AND_WRAP:		return "wrap";
905 		case VK_STENCIL_OP_DECREMENT_AND_WRAP:		return "decw";
906 
907 		default:
908 			DE_FATAL("Invalid VkStencilOpState value");
909 	}
910 	return DE_NULL;
911 }
912 
getStencilStateSetDescription(const VkStencilOpState & stencilOpStateFront,const VkStencilOpState & stencilOpStateBack)913 std::string getStencilStateSetDescription(const VkStencilOpState& stencilOpStateFront,
914 										  const VkStencilOpState& stencilOpStateBack)
915 {
916 	std::ostringstream desc;
917 
918 	desc << "\nFront faces:\n" << stencilOpStateFront;
919 	desc << "Back faces:\n" << stencilOpStateBack;
920 
921 	return desc.str();
922 }
923 
getFormatCaseName(VkFormat format)924 std::string getFormatCaseName (VkFormat format)
925 {
926 	const std::string fullName = getFormatName(format);
927 
928 	DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
929 
930 	return de::toLower(fullName.substr(10));
931 }
932 
933 } // anonymous
934 
createStencilTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)935 tcu::TestCaseGroup* createStencilTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
936 {
937 	const VkFormat stencilFormats[] =
938 	{
939 		VK_FORMAT_S8_UINT,
940 		VK_FORMAT_D16_UNORM_S8_UINT,
941 		VK_FORMAT_D24_UNORM_S8_UINT,
942 		VK_FORMAT_D32_SFLOAT_S8_UINT
943 	};
944 
945 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(compareOps) == 8);
946 	DE_STATIC_ASSERT(vk::VK_COMPARE_OP_LAST == 8);
947 
948 	static const char* compareOpNames[8] =
949 	{
950 		"comp_never",
951 		"comp_less",
952 		"comp_equal",
953 		"comp_less_or_equal",
954 		"comp_greater",
955 		"comp_not_equal",
956 		"comp_greater_or_equal",
957 		"comp_always"
958 	};
959 
960 	de::MovePtr<tcu::TestCaseGroup>		stencilTests				(new tcu::TestCaseGroup(testCtx, "stencil", "Stencil tests"));
961 	de::MovePtr<tcu::TestCaseGroup>		noColorAttachmentTests		(new tcu::TestCaseGroup(testCtx, "nocolor", "Stencil tests with no color attachment"));
962 	const bool							colorAttachmentEnabled[]	= { true, false };
963 
964 	for (deUint32 colorAttachmentEnabledIdx = 0; colorAttachmentEnabledIdx < DE_LENGTH_OF_ARRAY(colorAttachmentEnabled); colorAttachmentEnabledIdx++)
965 	{
966 		const bool							colorEnabled				= colorAttachmentEnabled[colorAttachmentEnabledIdx];
967 		de::MovePtr<tcu::TestCaseGroup>		formatTests					(new tcu::TestCaseGroup(testCtx, "format", "Uses different stencil formats"));
968 		StencilOpStateUniqueRandomIterator	stencilOpItr				(123);
969 
970 		for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(stencilFormats); formatNdx++)
971 		{
972 			const VkFormat	stencilFormat				= stencilFormats[formatNdx];
973 			const bool		hasDepth					= tcu::hasDepthComponent(mapVkFormat(stencilFormat).order);
974 			const bool		hasStencil					= tcu::hasStencilComponent(mapVkFormat(stencilFormat).order);
975 			const int		separateLayoutsLoopCount	= (hasDepth && hasStencil) ? 2 : 1;
976 
977 			for (int separateDepthStencilLayouts = 0; separateDepthStencilLayouts < separateLayoutsLoopCount; ++separateDepthStencilLayouts)
978 			{
979 				const bool			useSeparateDepthStencilLayouts	= bool(separateDepthStencilLayouts);
980 
981 				de::MovePtr<tcu::TestCaseGroup>	formatTest		(new tcu::TestCaseGroup(testCtx,
982 																						(getFormatCaseName(stencilFormat) + ((useSeparateDepthStencilLayouts) ? "_separate_layouts" : "")).c_str(),
983 																						(std::string("Uses format ") + getFormatName(stencilFormat) + ((useSeparateDepthStencilLayouts) ? " with separate depth/stencil layouts" : "")).c_str()));
984 
985 				de::MovePtr<tcu::TestCaseGroup>	stencilStateTests;
986 				{
987 					std::ostringstream desc;
988 					desc << "Draws 4 quads with the following depths and dynamic stencil states: ";
989 
990 					for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
991 					{
992 						const StencilTest::StencilStateConfig& stencilConfig = StencilTest::s_stencilStateConfigs[quadNdx];
993 
994 						desc << "(" << quadNdx << ") "
995 							 << "z = " << StencilTest::s_quadDepths[quadNdx] << ", "
996 							 << "frontReadMask = " << stencilConfig.frontReadMask << ", "
997 							 << "frontWriteMask = " << stencilConfig.frontWriteMask << ", "
998 							 << "frontRef = " << stencilConfig.frontRef << ", "
999 							 << "backReadMask = " << stencilConfig.backReadMask << ", "
1000 							 << "backWriteMask = " << stencilConfig.backWriteMask << ", "
1001 							 << "backRef = " << stencilConfig.backRef;
1002 					}
1003 
1004 					stencilStateTests = de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, "states", desc.str().c_str()));
1005 				}
1006 
1007 				stencilOpItr.reset();
1008 
1009 				for (deUint32 failOpNdx = 0u; failOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); failOpNdx++)
1010 				{
1011 					const std::string				failOpName	= std::string("fail_") + getShortName(stencilOps[failOpNdx]);
1012 					de::MovePtr<tcu::TestCaseGroup>	failOpTest	(new tcu::TestCaseGroup(testCtx, failOpName.c_str(), ""));
1013 
1014 					for (deUint32 passOpNdx = 0u; passOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); passOpNdx++)
1015 					{
1016 						const std::string				passOpName	= std::string("pass_") + getShortName(stencilOps[passOpNdx]);
1017 						de::MovePtr<tcu::TestCaseGroup>	passOpTest	(new tcu::TestCaseGroup(testCtx, passOpName.c_str(), ""));
1018 
1019 						for (deUint32 dFailOpNdx = 0u; dFailOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); dFailOpNdx++)
1020 						{
1021 							const std::string				dFailOpName	= std::string("dfail_") + getShortName(stencilOps[dFailOpNdx]);
1022 							de::MovePtr<tcu::TestCaseGroup>	dFailOpTest	(new tcu::TestCaseGroup(testCtx, dFailOpName.c_str(), ""));
1023 
1024 							for (deUint32 compareOpNdx = 0u; compareOpNdx < DE_LENGTH_OF_ARRAY(compareOps); compareOpNdx++)
1025 							{
1026 								// Iterate front set of stencil state in ascending order
1027 								const VkStencilOpState	stencilStateFront	=
1028 								{
1029 									stencilOps[failOpNdx],		// failOp
1030 									stencilOps[passOpNdx],		// passOp
1031 									stencilOps[dFailOpNdx],		// depthFailOp
1032 									compareOps[compareOpNdx],	// compareOp
1033 									0x0,						// compareMask
1034 									0x0,						// writeMask
1035 									0x0							// reference
1036 								};
1037 
1038 								// Iterate back set of stencil state in random order
1039 								const VkStencilOpState	stencilStateBack	= stencilOpItr.next();
1040 								const std::string		caseName			= compareOpNames[compareOpNdx];
1041 								const std::string		caseDesc			= getStencilStateSetDescription(stencilStateFront, stencilStateBack);
1042 
1043 								dFailOpTest->addChild(new StencilTest(testCtx, caseName, caseDesc, pipelineConstructionType, stencilFormat, stencilStateFront, stencilStateBack, colorEnabled, useSeparateDepthStencilLayouts));
1044 							}
1045 							passOpTest->addChild(dFailOpTest.release());
1046 						}
1047 						failOpTest->addChild(passOpTest.release());
1048 					}
1049 					stencilStateTests->addChild(failOpTest.release());
1050 				}
1051 
1052 				formatTest->addChild(stencilStateTests.release());
1053 				formatTests->addChild(formatTest.release());
1054 			}
1055 		}
1056 
1057 		if (colorEnabled)
1058 			stencilTests->addChild(formatTests.release());
1059 		else
1060 			noColorAttachmentTests->addChild(formatTests.release());
1061 	}
1062 
1063 	stencilTests->addChild(noColorAttachmentTests.release());
1064 
1065 	return stencilTests.release();
1066 }
1067 
1068 } // pipeline
1069 } // vkt
1070